Compare commits

...

233 Commits

Author SHA1 Message Date
Ali Sherif
1f438bd40f [Swift] Fix verifier accepting truncated scalar vectors (OOB read/write, RCE) (#9081) 2026-05-08 10:16:10 +02:00
mustiikhalil
392165432a [Swift] Migrate to use Swift Testing (#9076)
* Migrating from Xctests to swift testing

This migrates to the new Swift testing framework,
which would allow us to always use the latest tech
from swift moving forward.

* Updates flag to make sure that Wasm testing works
2026-05-07 21:49:41 -04:00
mustiikhalil
e6bbb3d22e [Swift] Migrate to swift 6.0 and Implements support gRPC v2 (#8983)
* Migrate to swift 6.0 & swift-gRPC 2.0

The following migrates to swift 6.0, and also
migrate to swift-grpc 2.0 that uses swift-nio
under the hood to provide nicer API and async await

Adds sendable to enum & update @_implementationOnly imports to use internal imports

* Address PR comments regarding misspelling & proper method naming.
2026-05-06 04:39:53 +02:00
Rifat Al Jubayer
a6979fe14a Fix logic inversion in FlexBuffers VerifyKey() (#9072)
VerifyKey() returns true on the first non-zero byte instead of
checking for a null terminator. This causes VerifyBuffer() to accept
FlexBuffers with non-null-terminated keys. Subsequent access to those
keys via strlen()/strcmp() reads out of bounds.

The condition if (*p++) should be if (!*p++) — return true
when a null terminator is found, not when any non-zero byte is found.

Confirmed with AddressSanitizer: heap-buffer-overflow in strlen()
after VerifyBuffer() returns true on a corrupted buffer.
2026-05-04 22:11:30 -04:00
Zen Dodd
bab10754d9 Stage the Python license file during builds (#9015)
Copy the repo-root LICENSE into the Python package directory for the duration of setup() so license_files = LICENSE remains valid without using deprecated parent-directory paths.

Remove the staged copy after the build completes.
2026-04-17 20:30:06 -04:00
Felix
ac7ef1176a Fix typo in generated header name (#9034) 2026-04-18 00:09:10 +00:00
Felix
d6444fb7fc Fix indention level for --no-python-gen-numpy (#9049) 2026-04-17 16:50:03 -04:00
Felix
e223d69b36 [Python] Extend GRPC Typing (#9007)
Extend function calls with optional type infos for checking
and discovering.

e838ba8a71/src/python/grpcio/grpc/__init__.py (L680)
2026-04-03 14:12:08 +00:00
Tulgaaaaaaaa
05cc7a2eff fix: correct operator precedence in ForAllFields reverse iteration (#8991)
* fix: correct operator precedence in ForAllFields reverse iteration

The expression `size() - i + 1` evaluates as `(size() - i) + 1` due to
left-to-right associativity, producing an out-of-bounds index when
reverse=true. For a vector of size N, the first iteration (i=0) accesses
index N+1, which is 2 past the last valid index.

Changed to `size() - (i + 1)` to match the correct implementation
already present in bfbs_gen.h:192.

Bug: CWE-125 (Out-of-bounds Read), CWE-783 (Operator Precedence Error)

* test: add ForAllFieldsReverseTest for reverse iteration correctness

Verify that ForAllFields with reverse=true iterates fields in
descending ID order. Tests both Stat (3 fields) and Monster
(many fields with non-sequential definition order) tables.

---------

Co-authored-by: Tulgaa <tulgaa.kek@gmail.com>
2026-04-02 10:14:27 +00:00
Noam ismach moshe
8a12183c3b Fix out-of-bounds vector access in StructDef::Deserialize (#8988)
* Fix out-of-bounds vector access in StructDef::Deserialize

* Fix syntax: use error_ instead of error()
2026-04-02 08:03:03 +00:00
Renzo
21b706b62d fix: swapped argument order in new_inconsistent_union calls (#9001) (#9010) 2026-04-02 07:05:58 +00:00
Tomasz Andrzejak
c5f151ab33 Add fallible try_* API for rust FlatBufferBuilder (#8918)
* Add fallible try_* API for FlatBufferBuilder

This is to support error propagation from Allocator trait. The Allocator
grow_downwards() method returns Result<(), Self::Error>, but
FlatBufferBuilder panics via .expect() when allocation fails instead of
propagating the error.

* Add rust fallible API docs
2026-04-02 06:49:51 +00:00
Björn Harrtell
3860f1cf7f [TS] Fixup TS test run at CI (#9004) 2026-03-30 13:32:24 +01:00
Thomas Köppe
4e582b0c1d [flexbuffers] Add "AlignedBlob", a version of "Blob" with explicit alignment. (#8993)
A blob is an array of bytes and has no intrinsic alignment (i.e. the
alignment is 1). The alignment of the existing flexbuffers blob is
solely affected by the width of the integer needed to store the blob's
size: that integer's width becomes the alignment of the blob.

The proposed AlignedBlob function here piggybacks on this effect and
simply uses a user-defined alignment for the width of the integer that
stores the blob's size; this automatically imparts that same alignment
on the blob itself. (The width is bounded below by the actual width
needed to store the blob's size.)

The ability to control the alignment of a blob is important for use
cases in which the blob itself stores structured data that we want to
access without further copies (e.g. other flatbuffer messages).
2026-03-23 10:28:03 -07:00
Fedor Osetrov
8396e00dd8 allow to use reflection in constant time evaluation (#8978)
* Update reflection.h

allow to use reflection in constant time evaluation

* make GetTypeSize constexpr

* fix clang-format
2026-03-20 02:01:45 +00:00
dependabot[bot]
48babd417d Bump flatted in the npm_and_yarn group across 1 directory (#8989)
Bumps the npm_and_yarn group with 1 update in the / directory: [flatted](https://github.com/WebReflection/flatted).


Updates `flatted` from 3.3.1 to 3.4.2
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.1...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 21:48:28 -04:00
tmimmanuel
22770f7e85 Fix inconsistent Python union creator function naming (#8981) 2026-03-19 12:36:37 +00:00
Dexter.k
21b033227e Add bounds check for root offset in AddFlatBuffer (#8982) 2026-03-19 08:22:26 -04:00
dataCenter430
93f587a6d3 fix: annotated output for size-prefixed binaries (#8976) 2026-03-18 22:54:46 -04:00
Kevin Zhao
8afb68f074 codegen: escape string default values to prevent code injection (#8964)
String default values parsed from .fbs schemas are un-escaped by the IDL
parser (e.g., \x22 becomes a raw " byte), but code generators embed these
raw values directly into generated source code string literals. This allows
specially crafted .fbs files to break out of string literals and inject
arbitrary code into generated C++, Rust, TypeScript, and Swift source.

Fix by adding EscapeCodeGenString() helper that re-escapes string content
before embedding, and applying it to all 7 affected injection points across
5 code generators (C++, Rust, TypeScript, Swift, FBS).

Resolves the TODO comments in idl_gen_cpp.cpp and idl_gen_rust.cpp.
2026-03-18 22:01:23 -04:00
Derek Bailey
2e07f269b9 Update build.yml
Remove 64-core windows github action runner as it is a charged product we need to do expense
2026-03-17 09:58:26 -07:00
Renzo
10c994155c Fix: allow flexbuffers alloc check test (#8972)
* Fix: allow flexbuffers alloc check test

* fix: flaky CI failure

* fix: set flexbuffers alloc check false
2026-03-12 09:44:32 -04:00
dataCenter430
fc9909c30a fix: infinite loop in proto reserved range parser (CWE-835) (#8966) 2026-03-11 22:23:32 -04:00
tmimmanuel
e35817577c Fix missing namespace qualifier in Pack() (#8967)
* Fix missing namespace qualifier in Pack() for cross-namespace table references

* Fix missing namespace qualifier in Pack()

* Add cross_namespace_pack_test to Bazel build
2026-03-11 22:11:06 -04:00
Moritz Walker
9e3fe5d3f6 rust: add secondary function with preallocated internal vecs (#8936)
* rust: add secondary function with preallocated internal vecs

* docs: document pre allocation feature for rust implementation
2026-03-11 15:26:23 +00:00
statxc
dc9217347e fix: add missing bracket (#8969) 2026-03-11 02:42:46 +00:00
statxc
a7fed2ce67 feat: add lookup_index_by_key to Rust Vector for index-based search (#8959)
* feat: add lookup_index_by_key to Rust Vector for index-based binary search

* fix: remove duplicated code
2026-03-11 02:15:21 +00:00
statxc
de3b97355d feat: use HashMap for create_shared_string to fix O(N²) performance (#8958)
* feat: use HashMap for create_shared_string to fix O(N²) performance

* refactor: clean up no_std binary_search_by with direct slice comparison
2026-03-10 21:56:34 -04:00
Renzo
8aa7084f01 Fix flaky flexbuffers_alloc_check test in cargo test (#8965) 2026-03-08 23:43:07 -04:00
Justin Davis
0f469cad54 Revert "fix using null string in vector (#7872)" (#8879)
This reverts commit 1cb1c4baee.
2026-03-07 13:19:34 +00:00
dependabot[bot]
72e51c61f7 Bump actions/upload-artifact from 6 to 7 (#8963)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-06 22:18:54 -05:00
Sutou Kouhei
31590a8a3b Enable Dependabot for GitHub Actions (#8778)
Our workflows use old GitHub Actions. For example, we use
`actions/checkout@v3` but `actions/checkout@v5` is the latest version:

599847236c/.github/workflows/build.yml (L33)

https://github.com/actions/checkout/releases

How about enabling Dependabot? If we enable Dependabot, Dependabot
opens PRs that update old GitHub Actions.

Dependabot document:
https://docs.github.com/en/code-security/dependabot

Dependabot configuration document:
https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference
2026-03-06 22:12:18 -05:00
Felix
24c2432d99 [Python]: Modernize setup and drop Python 2 (#8955) 2026-03-06 20:49:58 +00:00
Renzo
292870612c fix(flatbuffers): use manual impl Default for struct object types (#8947)
* fix(flatbuffers): use manual impl Default for struct object types

* fix: handle bool and float zero literals in struct object Default impl

* fix: regenerate all test bindings with generate_code.py

* fix: data type check on swift build

* fix: test large array on struct and enum
2026-03-06 11:20:32 -08:00
Cameron Mulhern
57659d9f38 Updates Rust codegen to use proper indentation (#8952)
* Fixes identation of generated Rust code

* Regenerates generated schemas
2026-03-05 14:04:55 +00:00
Udaya Prakash
2b8e4d3af0 build: Upgrade rules_swift to 3.1.2 and grpc to 1.76.0 (#8909) 2026-03-05 13:26:33 +00:00
Cameron Mulhern
08b6372a36 Generate better formatted Rust code (#8919)
* Cleans up Rust formatting

* Regenerates generated schemas
2026-03-05 02:49:46 +00:00
dependabot[bot]
9c383559e0 Bump minimatch in the npm_and_yarn group across 1 directory (#8951)
Bumps the npm_and_yarn group with 1 update in the / directory: [minimatch](https://github.com/isaacs/minimatch).


Updates `minimatch` from 3.1.2 to 3.1.5
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 02:43:14 +00:00
Salman Chishti
c13c3bf956 Upgrade GitHub Actions for Node 24 compatibility (#8934)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-03-04 21:36:59 -05:00
dependabot[bot]
47eeb8f4e9 Bump ajv in the npm_and_yarn group across 1 directory (#8933)
Bumps the npm_and_yarn group with 1 update in the / directory: [ajv](https://github.com/ajv-validator/ajv).


Updates `ajv` from 6.12.6 to 6.14.0
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0)

---
updated-dependencies:
- dependency-name: ajv
  dependency-version: 6.14.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 02:28:53 +00:00
Uwe (ObjectBox)
e7c6874192 [Dart] Actually use resized FlexBuffers buffer (#8935)
When building a FlexBuffer using the Builder and adding data that exceeds the default buffer size (2048 bytes), in _newOffset() a larger buffer is created, but never used. This results in a RangeError.

Resolve by actually replacing the too small with the new larger buffer. Add a test that verifies this by adding multiple large strings to a vector.
2026-03-05 02:15:45 +00:00
RCRalph
8d2c333b36 fix: Added return value to non type-prefixed create vector function (#8945)
* fix: Added return value to non type-prefixed create vector function

* chore: Added generated code
2026-03-05 02:09:09 +00:00
Damian Sypniewski
abc9bfebff Update Go support for Optional Scalars (#8946) 2026-03-04 21:03:49 -05:00
Abhay Agarwal
94d6b8086b Ensure optional arrays, arrays with defaults, and strings with defaults are supported (#8896)
Fixing issues with generated ts/js
2026-02-23 08:55:37 +01:00
dependabot[bot]
fa709636b4 Bump lodash (#8913)
Bumps the npm_and_yarn group with 1 update in the /tests/ts/bazel_repository_test_dir directory: [lodash](https://github.com/lodash/lodash).


Updates `lodash` from 4.17.21 to 4.17.23
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-19 01:09:46 +00:00
Stevan Coroller
60463e25a8 Remove empty 'required' section from schema.md (#8900)
There is a typo in the schema.md file in documentation. An empty 'required' section was added right before the 'required' item in the middle of the attributes list. It even appears in the table of content, which might confuse readers, making it look like following attributes might be required while they are not. You can notice the issue there: https://flatbuffers.dev/schema/#attributes.

I did check that `mkdocs serve -f mkdocs.yml` does produce the expected output (the same attributes list without that extra empty `required` section in the middle) with my changes.
2026-02-18 20:03:01 -05:00
Austin Chick
b8e3d215b8 [TS] Fix relative import paths of generated TypeScript code (#8880)
* Refactor logic that generates import paths in AddImport

* Add new tests to validate relative import path fix

* Generate goldens

* Generate example code

* Format TS generator file

* Revert "Format TS generator file"

This reverts commit 0f0b24aee9.

* Fix merge conflicts

---------

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2026-02-17 10:22:32 +01:00
mustiikhalil
d71c0ab4ac Moves the internal stack to use a pointer stack instead of the native array for improved performance (#8891)
Remove custom flags for native arrays when using flexbuffers on Wasm

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2026-02-12 19:42:21 +01:00
mustiikhalil
fcf75449b8 [Swift] Moves VTs from enums to structs to prevent empty enum generation
Moves VTs from enums to structs to prevent empty enum generation, which would usually cause a compilation error.
2026-02-12 08:04:26 -10:00
Sebastian Barfurth
c21bda1649 Remove root_package from npm_translate_lock. (#8921)
This attribute is removed in the next major version of `aspect_rules_js`. It's
not actually needed here [according to](https://github.com/aspect-build/rules_js/pull/2709#issuecomment-3855183151)
a maintainer of `aspect_rules_js`.
2026-02-07 08:04:22 +00:00
Marcel
03fffb25e2 Set max_compatibility_level=3 for rules_swift (#8920)
This is necessary to be compatible with both rules_swift 2.x and 3.x.
2026-02-05 09:57:00 -08:00
bigjt
1a7495a6dd [C#] Add GetBytes methods for fixed arrays (#8633)
* [C#] Add GetBytes methods for fixed arrays

I wanted to direct access to fixed array bytes. I made some changes to the idl generator to create GetBytes functions following the same naming conventions used for vectors of scalar types. There was not a 'Length' field present to bound the existing index accessor so I added that too.

+ Add generic GetBytes for fixed length arrays of scalar types
+ Implement conditional compilation for ENABLE_SPAN_T:
  - ENABLE_SPAN_T: Returns `Span<T>` using `MemoryMarshal.Cast<byte, T>()` as needed.
  - Else: Returns `ArraySegment<byte>?` for raw byte access
+ Added tests reusing arrays_test.fbs definitions
+ Added const int Length field to support existing index based accessors

* [C#] Sync generated code for after adding GetBytes methods for fixed arrays

---------

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2026-02-04 23:13:32 +00:00
Fawdlstty
3c1bb67ae1 sync human-readable value (#8859)
Co-authored-by: Justin Davis <jtdavis777@gmail.com>
2026-02-04 15:43:19 +00:00
Cameron Mulhern
5b9de8b6c0 Fixes Rust code generation for single file output when using namespaces (#8877)
* Adds tests for Rust single file mode

All existing tests only compile Rust code using --rust-module-root-file.

* Adds standalone include tests for Rust

The imports for these tests have been moved to their own file, as the existing intergration_test.rs file hides compilation issues from code generation due to symbols brought into scope outside of the generated code (e.g. `extern crate alloc`).

* Declare alloc crate in every Rust namespace

When performing code generation within a single file, extern crate alloc needs to be delcared to bring alloc into scope within every inner namespace.

* Regenerates generated schemas
2026-02-04 15:28:18 +00:00
Justin Davis
ea0a73d168 disallow circular struct references (#8851)
* detect and fail for circular struct dependencies

* pr comments

* pr comment
2026-02-04 15:15:05 +00:00
souma987
4623cfa4bc Opt in to using experimental Kotlin Native APIs to suppress build warnings (#8885)
- fixes #8846
2026-02-04 14:54:08 +00:00
Peter Shih
9c2c56dc6a Fix typo in comment in idl.h (#8907)
Co-authored-by: Justin Davis <jtdavis777@gmail.com>
2026-02-04 14:12:50 +00:00
brianmacy
429c28c783 fix(rust): Zero vtable memory in write_vtable to prevent uninitialized data (#8898)
The write_vtable() function's comment claimed to "fill the WIP vtable
with zeros" but make_space() only reserves memory without initializing
it. When using custom allocators with non-zeroed buffers, unset vtable
field entries would contain garbage instead of zero (which indicates
"use default value").

This fix explicitly zeros the vtable memory after reserving space,
matching the C++ implementation's buf_.fill_big() behavior.

Added regression test using a garbage-filled allocator (0xAA) that
verifies vtable entries for unset fields are properly zeroed.

Fixes #8894
2026-02-04 09:00:44 -05:00
Markus Junginger
e5a9ff757f flatbuffers.h: fix C++11 compilation (#8857) (#8858)
This constexpr officially works only with C++14 (assignment to lhs, 2 statements) and actually broke some C++11 compilers
2026-02-04 13:34:55 +00:00
Justin Davis
e53732b9b9 Feature: lua now file_ident aware (#8850)
* lua code not file ident aware

* update genned code

* make mac happy

* pr comments
2026-02-04 13:05:08 +00:00
Thiébaud Weksteen
b84b676c89 Fix example of JSON export with flatc (#8892)
Binary files should be placed after "--". Also add a note about missing
file_identifier and --raw-binary.
2026-02-04 07:51:49 -05:00
Iñaki Baz Castillo
3211f857d1 Add --ts-undefined-for-optionals command line option (#8861)
* Add --ts-undefined-for-optionals command line option

# Details

- Fixes #7656
- Added a new `--ts-undefined-for-optionals` command line option for `flatc`.
- If enabled, generated TypeScript code uses `undefined` for optional fields rather than `null`.

* Also add TS generated test files

* Run `sh scripts/clang-format-git.sh`

* also add tests/ts/lalala-options.ts to the repo

* move new tests to tests/ts/optional_values dir

* add tests/ts/optional_values/optional_values_generated.cjs to the repo

* reuse existing optional_scalars.fbs and add new test

* add comma

* sh scripts/clang-format-git.sh

* remove comma

* sh scripts/clang-format-git.sh

* trying things

* sh scripts/clang-format-git.sh

* done

* address feedback

* sh scripts/clang-format-git.sh

* run `sh scripts/clang-format-git.sh`

* remove uneeded `eslint-disable @typescript-eslint/no-namespace` line

---------

Co-authored-by: José Luis Millán <jmillan@aliax.net>
2026-02-04 13:37:41 +01:00
Stefan F.
95ff1f1d80 [c#] Fix Table __vector_as_array correct len calc (#8911)
* fix for https://github.com/google/flatbuffers/issues/8759
__vector_as_array<T> calling ByteBuffer.ToArray<T> with the length in bytes by multiplying len with ByteBuffer.Sizeof<T> and FlatBuffersExampleTests extended to call GetVectorOfLongsArray/GetVectorOfDoublesArray which failed without the fix

* first try to repair build-dotnet-windows

* syntax error fixed

* Update solution creation command in build workflow

add --format sln to the dotnet new command, maybe it is currently creating a .slnx instead?
2026-02-04 13:13:01 +01:00
Jacob Abrams
af8997b567 [Python] Improve python API (#8781)
* Fix generate_code script path

* [Python] Make StartVector public

Make StartVector vector public since it is already being used in
generated code

* [Python] Improve vector creation for Python API

Makes Python API for vectors cleaner like Rust and Swift

---------

Co-authored-by: Derek Bailey <derekbailey@google.com>
2026-01-21 01:01:20 +00:00
Derek Bailey
0d67abde45 MODULE.bazel: Upgrade rules_swift version (#8908) 2026-01-20 16:56:11 -08:00
razvanalex
d74e2945f7 [C++] Check for case insensitive keywords (#8420)
* chore(idl): Check for case insensitive keywords

Most languages are not affected by this change. In PHP, some names such
as Bool cannot be used because it is a reserved keyword for to the bool
data type. The field `keywords_casing` in the configs enables checking
all characters in lowercase against every keyword. This should be safe
as flatbuffers does not allow non-ASCII characters in its grammar.

* chore: Fix formatting to follow google's coding style for enums

* chore: Extract convert case to lower when CaseInsensitive

---------

Co-authored-by: Justin Davis <jtdavis777@gmail.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2026-01-20 16:06:07 -08:00
Nicolas Ulrich
8914d06ab7 Remove invalid dependency on FLATBUFFERS_GENERATE_HEADERS_SCHEMAS (#8834)
* Remove invalid dependency on FLATBUFFERS_GENERATE_HEADERS_SCHEMAS

add_dependencies() is for targets.

CMake 4.2.0 fails because of this (it shouldn't crash though, but that's another topic). See https://gitlab.kitware.com/cmake/cmake/-/issues/27415

* Use FLATC_TARGET

---------

Co-authored-by: Justin Davis <jtdavis777@gmail.com>
2025-12-22 02:25:14 +00:00
Derek Bailey
522f2379a6 Update CODEOWNERS 2025-12-21 16:10:34 -08:00
Justin Davis
7cb0bcb212 C++ Feature: Mutable union getters (#8852)
* generate mutable union accessors

* add test

* Revert "add test"

This reverts commit 45e352b18f.

* update file

* formatter got in the way

* merge conflicts

* updated genned code

* manually fix code gen bc I can't figure out why this file won't code gen

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-12-21 17:36:47 -05:00
Justin Davis
b1e7868db6 add verification that type_vec.size == vec.size() (#8853)
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-12-21 21:55:54 +00:00
Justin Davis
68e3c839c3 update provenance (#8873) 2025-12-21 21:50:57 +00:00
mustiikhalil
0723245085 [Swift] Fixes bazel.build file allowing it to find Vectors folder in 8.5.0 (#8875) 2025-12-21 21:22:49 +00:00
Ville Vesilehto
9d64b9c0c0 fix(go): add bounds checking to ByteVector (#8776)
Add missing bounds checking to ByteVector before slice
operations in the Go FlatBuffers implementation. Relative offset and
vector length are now checked against the buffer size. Instead of
panicking, the code now returns nil. Regression test added.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Co-authored-by: Justin Davis <jtdavis777@gmail.com>
2025-12-21 20:25:30 +00:00
Justin Davis
d01f20f2fb Fix python generation with nested flatbuffers (#8854)
* implement fix from issue

* implement actual fix
2025-12-21 11:18:05 -08:00
Derek Bailey
7e163021e5 FlatBuffers Version 25.12.19 (#8871) 2025-12-19 15:06:07 -08:00
Derek Bailey
57fdd4f995 Default Vector Support C++ (#8870) 2025-12-19 14:32:51 -08:00
Derek Bailey
8cb53ccc95 Add --gen-absl-hash option to generate AbslHashValue for structs. (#8868) 2025-12-19 11:49:50 -08:00
Derek Bailey
fb55e0c9de Run clang-format -i **/*.cpp (#8865) 2025-12-19 10:42:57 -08:00
Derek Bailey
d9fde67eb5 Remove progaurd-rules.pro (#8866) 2025-12-19 09:54:43 -08:00
Derek Bailey
f74fda299d Update CODEOWNERS
Ensure no-one can add to owners other than myself as the official Google representative of this repo.
2025-12-18 17:14:33 -08:00
Derek Bailey
15802fa26c Create CODEOWNERS
Add a CODEOWNERS files to assign ownership to different parts of the code base
2025-12-18 17:03:50 -08:00
souma987
a86afae939 Fix casing in generated Kotlin struct constructor function (#8849)
* fixes #8419
2025-12-14 23:59:17 +00:00
souma987
60910fb7f5 Fix nullability of generated Kotlin ByteBuffer accessors (#8844)
* fixes #8691
2025-12-14 18:56:40 -05:00
Justin Davis
7bfaabc358 [TS] Flexbuffers root vector fix (#8847)
* fix and test

* chatgpt help

* consistent throws in reference.ts
2025-12-14 22:59:27 +01:00
Justin Davis
e1407e4341 Upgrade Kotlin to MacOS 15 (#8845)
* upgrade kotlin and macos

* remove xcode version selection
2025-12-14 13:28:24 -05:00
Justin Davis
c9a301e601 Arrays of Enumerations without a value for 0 are no longer valid (#8836)
* arrays of enums with no value for 0 now throw errors

* move setting key field outside struct check

* set to default instead of required

* unsure of why these bfbs files have changed at this time, checking them in to run the pipelines.

* remove known bad test
2025-12-13 18:40:58 -05:00
James Thompson
19b2300f93 chore: switch package to license expression (#8840)
* switch package to license expression

* Remove license file from package
2025-12-10 09:50:50 -05:00
Justin Davis
e60c0ab9e2 deprecate the two options which have no effect of their own (#8831) 2025-12-08 06:03:11 -05:00
Justin Davis
541dd1a8f5 Fix vector of table with naked ptr (#8830)
* create test that fails to compile

* fix the issue

* add test body

* force commit gneerated header

* build failures

* fix bazel some more
2025-12-07 11:05:54 -08:00
Justin Davis
7711e84919 Fix TS object API generation of schema containing array of enumeration having no zero default (#8832)
* set the array constructor to fill with minvalue

* add regression generation test
2025-12-07 07:35:38 -05:00
Kende Gömöri
89430a14d6 Fix docs: typo & dead link (#8826)
* Fix CHANGELOG.md

* Fix broken doc link
2025-12-05 20:31:04 -05:00
Cameron Mulhern
cfce38ec99 Fixes unused imports in Rust code generator (#8828)
* Fixes unused imports in Rust code generator

* Regenerates generated schemas
2025-12-04 21:59:47 -08:00
Justin Davis
5469bc9ef1 Update flatc.md (#8821) 2025-12-03 14:16:59 +01:00
Ky0toFu
b39f79e5e9 Fix(ts): escape doc comment terminator in generated JSDoc (#8820) 2025-12-03 12:26:13 +00:00
Justin Davis
dc623919bd update docs (#8819)
Fixes #8733
2025-12-03 07:31:49 +01:00
Justin Davis
a1e125af11 Implement --file-names-only (#8788)
* flatc builds and seems to work, some of the extra targets are having linker errors

* fix build system

* pipeline failures

* un-rename files

* refactor to use unique_ptr

* typo

* rm make_unique, add comments

* fix cmake

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-12-03 04:37:06 +00:00
Richard Patel
0b60686e3d rust: impl TrustedLen for VectorIter (#8797)
Improves unpack performance for vectors by allowing the compiler
to vectorize flatbuffers::Vector to std::vec::Vec conversions,
using the unstable trusted_len feature.

Internally, enables an optimization in src/alloc/vec/spec_extend.rs:
Previously, unpacking a flatbuffers::Vector called
SpecExtend::extend_desugared fallback, which inhibits vectorization
(due to a branch before every element move).  Declaring TrustedLen
allows SpecExtend::extend_trusted, which LLVM can often vectorize
into a memcpy.

For [ubyte] vectors in particular, this turns a rather expensive
loop of 'mov BYTE PTR [rax+r13*1], bpl' into a `call memcpy`.
2025-12-03 04:21:16 +00:00
Fawdlstty
17ceaae16e [rust] add deser support for enum type (#8803)
* add deser support for enum type

* update generated files

* remove deser generator when bitflag enable

* add deser test

* Restore the Rust editions version

* Remove unnecessary modifications
2025-12-02 22:48:45 -05:00
Rob Jellinghaus
a5343d6116 fix(idl_gen_rust): Fix lifetime warning added in Rust 1.89 (#8709)
Rust 1.89 added a new lifetime-related warning:
<https://blog.rust-lang.org/2025/08/07/Rust-1.89.0/#mismatched-lifetime-syntaxes-lint>

The Rust code generator currently emits code which trips this warning. This very small PR
fixes the issue for the relevant generated functions and for the Rust flexbuffers code.

Fixes #8705
2025-12-02 22:27:40 -05:00
Justin Davis
4786322b90 update labeler.yml to v5+ format (#8818) 2025-12-02 21:21:25 -05:00
Cameron Mulhern
646a8bc96a Improves Rust code generation (#8564)
* Fixes checks for serde features in flexbuffers crate

* Removes unused MapReaderIndexer use statement

* Fixes warning about nightly cfg usage

Enabling a cfg attribute through cargo::rustc-cfg in build.rs should be coupled with a cargo::rust-check-cfg value so that the compiler knows about the custom cfg. See: https://doc.rust-lang.org/rustc/check-cfg/cargo-specifics.html#cargorustc-check-cfg-for-buildrsbuild-script.

* Migrates usage of deprecated float constants

This update fixes a compiler warning from use of the old constants.

Constants like EPSILON are now directly on the float primitives (e.g. f32::EPSILON) rather than in the f32 module (std::f32::EPSILON).

The new constants have existed since 1.43.0, which appears to be below the MSRV for the flatbuffers crate.

* Fixes incorrect key in flatbuffers Cargo.toml

The old code was using package.rust, which triggered a warning about an unused key:

warning: flatbuffers/rust/flatbuffers/Cargo.toml: unused manifest key: package.rust

The correct key for specifying MSRV is rust-version. See: https://doc.rust-lang.org/cargo/reference/rust-version.html#rust-version.

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-12-02 18:06:24 -08:00
Felix
0e3471d6a7 WIP error messages (#8764)
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-12-02 17:52:30 -08:00
Felix
b07589a0f9 CI: Fix typo in version (#8817) 2025-12-02 16:14:43 -05:00
mustiikhalil
2062c33cd4 Add support for Flexbuffers in wasm (#8815) 2025-12-02 16:18:24 +01:00
Felix
adb7add87e Modernize GitHub CI actions (#8812)
* CI: Modernize actions/checkout

* CI: Modernize actions/stale

* CI: Modernize softprops/action-gh-release

* CI: Modernize microsoft/setup-msbuild

* CI: Modernize gradle/actions/setup-gradle

* CI: Modernize actions/setup-dotnet

* CI: Modernize actions/setup-java

* CI: Modernize jiro4989/setup-nim-action

* CI: Update to latest image seems to be fixed

The readme list swift now for 24.04

* CI: Update to latest actions/labeler tag instead of sha
2025-12-02 10:11:55 -05:00
mustiikhalil
29f99937c4 Migrating to swift wasm on for github actions (#8814)
Migrate to use the native SDK for Wasm that's built for swift
2025-12-02 02:13:22 +01:00
Jacob Abrams
597e76a268 Optimize Offset/Pad/Prep: use cached head and slicing, reduce casting (#8808) 2025-12-01 19:00:20 -05:00
Wakahisa
a577050817 [Java] Use Table's fully qualified path (#8729)
* [Java] Use Table's fully qualified path

When a table's name is called `Table`, the Java bindings generated result in an error due to there being  2 Tables. This fixes the issue by fully qualifyng the flatbuffers Table import.

* Update codegen

* Update generated Java code

---------

Co-authored-by: Neville Dipale <neville@urbanlogiq.com>
2025-12-01 11:28:50 -05:00
razvanalex
31ab0bf6c8 [Go] Write required string fields into the buffer when using Object API (#8402)
* [Go] Write required string fields into the buffer when using Object API

In C++, CreateX allows to write the default "" value of a required
string, when the string is not explicitly set. Object API Pack method
uses this implementation of CreateX.

However, in go, despite whether the field is optional or required, it is
always checked against empty string allowing to create messages that
fail to pass the verifier. This commits partially reverts #7719 when the
string field is required.

* Add test for serializing required string fields using Object API

* Update generated code

The Monster schema contains a key string field. For historical
convenience reasons, string keys are assumed required.
2025-12-01 09:50:03 -05:00
Jeroen Demeyer
e4775aa3fe [Go] add BenchmarkBuildAllocations (#8287) 2025-11-30 22:12:12 -05:00
whiteye
97d26ab4ae fix CScript string.compare (#8547)
* fix CScript string.compare

Because the default compare sorting rules of c# string are different from those of cpp, the binary file exported by flatc -b cannot use LookupByKey

* run generate_code.py

---------
2025-11-30 22:06:41 -05:00
James Robinson
7dd38fa23a Fix platform ifdefs for locale independent str functions (#8678)
Android libraries include <android/api-level.h> which defines the __ANDROID_API__ symbol even when targeting non-Android platforms and not using Android's libc. This updates the FLATBUFFERS_LOCALE_INDEPENDENT ifdef to check for __ANDROID__ before checking the Android API level.

Removes an extra check from the __Fuchsia__ branch. Fuchsia's libc does not support locales or the locale independent entry points.

Updates the Android API check to check for an API level >= 26 instead of 21. This matches the Android header file's availability macros and Bionic documentation:

https://android.googlesource.com/platform/bionic/+/HEAD/docs/status.md
2025-11-30 21:38:37 -05:00
Jacob Abrams
7350c3668f Optimize Builder startup: lazy sharedStrings and fast vtable init (#8807) 2025-11-30 23:33:34 +00:00
Felix
49d2db93a7 [Python] Fix generating __init__.py for invalid path (#8810)
This tried to generate from a directories "MyGame/Sample/"
for a empty path_ in M, MyGame & MyGame/Sample.
Which is incorrect since we want to start with the first
kPathSeparator `/` and not position 1.
2025-11-30 23:30:55 +00:00
Uilian Ries
807b43c0d7 Remove legacy Conan recipe and update documentation (#8712)
* Remove legacy Conan recipe

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* Document how to install flatbuffers with Conan

Signed-off-by: Uilian Ries <uilianries@gmail.com>

---------

Signed-off-by: Uilian Ries <uilianries@gmail.com>
Co-authored-by: Justin Davis <jtdavis777@gmail.com>
2025-11-30 11:35:02 +00:00
peter-soos
4b823b1b98 [Python] Fix inconsistent creator function naming in generated code (#8791) (#8792) 2025-11-29 16:48:53 -05:00
mustiikhalil
4c47f4c11e Revert back to using swift-actions (#8806)
Reverting to swift-actions since they seem to have fixed the issue with GPG keys
2025-11-27 21:56:20 -05:00
coder7695
2b107e20c5 [fuzzer] Adds code generation target. (#8795)
* adds code generation fuzzer target.

* add buffer verification

* add table verification in codegen fuzzer

---------

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-11-27 15:52:28 +00:00
Jacob Bandes-Storch
84f4b83d3e TypeScript: read vtable entries as uint16 (#8435)
Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-11-27 10:55:34 +00:00
dependabot[bot]
185e41fac4 Bump js-yaml in the npm_and_yarn group across 1 directory (#8779)
Bumps the npm_and_yarn group with 1 update in the / directory: [js-yaml](https://github.com/nodeca/js-yaml).


Updates `js-yaml` from 4.1.0 to 4.1.1
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-11-27 11:50:31 +01:00
Grzegorz Owsiany
8b02fe6178 [C++] Fix vtable deduplication for 64-bit buffers >2GB (#8591)
Fixes #8590
2025-11-26 21:12:24 -05:00
Sutou Kouhei
6e0dad8c5f Use macos-15-intel not macos-latest-large for Intel macOS (#8777)
We can't use macos-latest-large in non paid GitHub account but we can
use macos-15-intel in public repositories. If we use macos-15-intel,
we can run CI jobs for Intel macOS in fork repositories.
2025-11-26 19:31:24 -05:00
obones
e3e355d498 feat: library definition for PlatformIO (#8261)
* feat: library definition for PlatformIO

* Update library.json version with release.sh

---------

Co-authored-by: Flávio Zanoni <flaviozg888@gmail.com>
2025-11-26 19:18:13 -05:00
Jakob Kordež
8e901ce17c Fix dart object api test (#8751) 2025-11-26 17:36:08 -05:00
Yuanyuan Chen
7808ae5c88 More robust <span> check (#8631) 2025-11-26 17:33:06 -05:00
Wakahisa
20068cfa05 [Java] Add notify to Java keywords (#8724)
Fixes #8723

Co-authored-by: Neville Dipale <neville@urbanlogiq.com>
Co-authored-by: Max Burke <max@urbanlogiq.com>
2025-11-26 07:59:18 -08:00
Wakahisa
afd07bdec5 [Java] Generate Longs from uint enums (#8727)
Co-authored-by: Neville Dipale <neville@urbanlogiq.com>
Co-authored-by: Max Burke <max@urbanlogiq.com>
2025-11-26 07:58:25 -08:00
Hjalti Leifsson
2951d5383a chore: fix quick start typos (#8520)
* chore: fix another typo

* chore: undo overzealous IDE changes
2025-11-25 16:24:23 -05:00
Glenn Fiedler
ba563de877 add assert to fix GCC warning on Ubuntu 24.04 LTS (#8804) 2025-11-25 14:08:51 -05:00
Fawdlstty
46a2f3f2c2 [dart] fix bug which generated wrong code (#8780) 2025-11-24 10:54:43 -05:00
Ivan Dlugos
7675121eab Add Dart changelog entry for v25.9.23 (#8785)
Documents changes included in the Dart package v25.9.23 release,
which was published to pub.dev.
2025-11-24 09:18:23 -05:00
Benjamin Kietzman
ea2b5148e5 Fix issue #8389: any nonzero byte is truthy (#8690) 2025-11-24 07:26:39 -05:00
Fergus Henderson
20548ff3b6 Size verifier fix 2 (#8740)
* Fixes to make SizeVerifier work.

In particular change all the places in the Flatbuffers library
and generated code that were using `Verifier` to instead use
`VerifierTemplate<TrackBufferSize>` and wrap them all inside
`template <bool TrackBufferSize = false>`.

Also add unit tests for SizeVerifier.

* Format using `sh scripts/clang-format-git.sh`

* Use `B` rather than `TrackBufferSize` for the name of the template parameter.

* Update generated files.
2025-11-24 07:11:32 -05:00
Jacob Abrams
7ea8db05d8 [Python] Add unit test for github issue 8653 (#8786) 2025-11-24 06:41:50 -05:00
Justin Davis
c7b6b66ccb fix: remove a single type hint to retain 2.7.x compatibility (#8799)
Co-authored-by: Hjalti Leifsson <hjaltileifsson@gmail.com>
2025-11-23 12:00:21 -08:00
Justin Davis
ac8b124496 don't crash on a lua file with no root table (#8770)
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-17 22:31:32 +00:00
Justin Davis
88b033b964 add proposed fixes from #8731 (#8771)
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-17 13:46:41 -08:00
Justin Davis
e68355cb22 [C++] Add Vector64 specialization for std::vector<bool> (#8757)
* add vector64 specialization for vector<bool>

* fix generated code

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-17 13:44:28 -08:00
Justin Davis
e3ee24830e Fix Issue #8653 - Python vtables not considering object size (#8683)
* have vtables consider size

* simplification from comment

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-17 13:43:28 -08:00
Felix
2a8f4568e0 Replace usage of make_unique with unique_ptr for cpp11 (#8763) 2025-11-17 13:42:06 -08:00
mustiikhalil
cbf0850828 [Swift] Inline arrays (#8755)
Implements InlineArrays which allow us to use Flatbuffers arrays within
Structs natively, and also implements FlatbufferVectors as a secondary API
when using mutable Structs

Fixes mutations within fixed sizes arrays

Adds tests and remove inout and mutating from generated objects in favor of borrowing

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-15 00:33:16 +01:00
mustiikhalil
7150dfb5c4 [Swift] Bump minimum supported version of swift to 5.10 (#8758) 2025-11-14 15:07:49 -08:00
mustiikhalil
fa87eccd1a Update swift supported features (#8769) 2025-11-14 15:07:25 -08:00
mustiikhalil
a62f45fed8 Improves the performance of the string imp (#8772)
Improves the performance of the implementation in Swift
by using withCString instead of the contigiousString
2025-11-14 15:06:52 -08:00
cosmith-nvidia
599847236c Support native_type for tables when using the C++ object API. (#8668)
* Support native_type for tables when using the C++ object API.

If native_type is specified on a table:
- No object API struct type is generated.
- The object API refers to the table by its native_type.
- UnPack and Create<TableName> methods are declared but not defined; as they
  must be user-provided.

* Add tests for native_type on tables.

* Add documentation for native_type on tables.
2025-11-05 07:50:10 -08:00
cosmith-nvidia
4173b84d4b Fix --gen-compare to not generate comparators for native types. (#8681)
Per the definition of --gen-compare: only generate comparators for object API
generated structs. Types annoated with native_type must define their own
comparators if `--gen-compare` is enabled.

Also enables --gen-compare for native_type_test and fixes the test by adding a
comparator for the Native::Vector3D type.
2025-11-05 00:43:00 +00:00
mustiikhalil
5fe90a9160 [Swift] Implements FlatbuffersVector which confirms to RandomAccessCollection (#8752)
* Implements FlatbuffersVector in swift

Implements FlatbuffersVector which confirms to RandomAccessCollection,
this would give us semi-native sugary syntax to all the arrays in swift port.

This work will also be the foundation of using arrays in swift

* Fix failing tests for Swift
2025-11-04 23:53:59 +00:00
cosmith-nvidia
78a3d59a65 Swap the dependency of CreateX and X::Pack object API functions. (#8754)
Previously: X::Pack forwarded to CreateX.

Now: CreateX will forward to X::Pack.

This is a step toward enabling using native types for tables when using the
object API. When defining a native table, the user will be able to define a
custom X::Pack method (which is more consistent with the existing native_type
functionality for structs). By reversing the order of the dependencies, CreateX
can continue to be auto-generated and will use the custom X::Pack method when
overriden for native_type tables.
2025-11-04 15:42:16 -08:00
are-you-tilted-already
5ed02dc04a Prevent make_span from working with vectors and arrays of pointers (#8735)
* Prevent `make_span` from working with vectors and arrays of pointers

* support `make_structs_span` for little-endian

* fix build: add the required parentheses

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-11-04 13:47:44 -08:00
Jakob Kordež
592dc50037 Refactor lazy list unpacking (#8746)
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-10-31 13:41:59 -07:00
coder7695
dd77af75b7 Add conditional check (#8736)
* resolve windows compile error

* add conditional for undef new

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-10-31 11:20:18 -07:00
Jakob Kordež
051604aeb5 Fix struct vector ordering in pack function (#8747) 2025-10-31 09:59:01 -07:00
Jakob Kordež
4b09586652 Fix union unpacking (#8748) 2025-10-31 09:58:30 -07:00
David Sanderson
4c0eecd25a treat npm_typescript as a dev dependency (#8719)
Treat flatbuffers' definition of npm_typescript as a dev dependency, in order to avoid conflicts when consuming flatbuffers in a repo that also depends on aspect_rules_ts.
2025-10-30 07:49:54 -07:00
mustiikhalil
de25052c72 Fixes failing tests on macOS due to file loading (#8742)
Fixes failing tests due to the usage of URL(fileURLWithPath:isDirectory:) instead of URL(string:)
2025-10-29 11:36:47 -07:00
vsmcea
95053e6a47 Correct span and non-span versions of ToArray() and ToArrayPadded() methods (#8734)
* Correction of bug inside ToArray<T> methods

Avoid allocating too large buffers (len is expressed in bytes, not in Ts).
Added validation to ensure len is a multiple of SizeOf<T>() before converting to array.

* Update ByteBuffer.cs

* Refactor ToArray and ToArrayPadded methods

I understand from failed test that pos, len, padLeft and padRight are expressed in Ts

* Refactor ToArray and ToArrayPadded methods

* Final correction
All functions parameters expressed in bytes for homogeneity
Tests run:
  - UNSAFE_BYTEBUFFER=true/ENABLE_SPAN_T=true: passed
  - UNSAFE_BYTEBUFFER=true/ENABLE_SPAN_T=false: passed
  - UNSAFE_BYTEBUFFER=false/ENABLE_SPAN_T=false: passed
  - UNSAFE_BYTEBUFFER=false/ENABLE_SPAN_T=true: configuration forbidden by compilation
Correction of FlatBuffers.Test.csproj to allow UNSAFE_BYTEBUFFER/ENABLE_SPAN_T tests
Correction of FlatBuffersExampleTests.cs: I think the test was not run because it could not pass (to be reviewed carefully)
2025-10-25 11:58:05 -07:00
Daniel Nguyen
27325e002a docs: clean up whitespace and fix typo in tutorial.md (#8695)
* docs: remove trailing whitespace

* docs: fix typo in tutorial.md
2025-09-25 09:02:22 -07:00
Derek Bailey
1872409707 FlatBuffers Version 25.9.23 (#8708) 2025-09-23 22:18:02 -07:00
dependabot[bot]
c427e1a65d Bump the npm_and_yarn group across 1 directory with 2 updates (#8704)
Bumps the npm_and_yarn group with 2 updates in the / directory: [@eslint/plugin-kit](https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit) and [brace-expansion](https://github.com/juliangruber/brace-expansion).


Updates `@eslint/plugin-kit` from 0.3.2 to 0.3.5
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/plugin-kit/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/plugin-kit-v0.3.5/packages/plugin-kit)

Updates `brace-expansion` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: "@eslint/plugin-kit"
  dependency-version: 0.3.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2025-09-23 21:54:56 -07:00
Derek Bailey
caf3b494db bulk code format fix (#8707) 2025-09-23 21:50:27 -07:00
Derek Bailey
0e047869da Use the Google Style for clang-format without exceptions (#8706)
This reduces the friction when merging from github and google repos by
using the exact same clang style guide.

MARKDOWN=true
2025-09-23 21:19:33 -07:00
mustiikhalil
881eaab706 Revert back to use the latest from the swiftly ci (#8702) 2025-09-21 21:47:05 -07:00
nurbo
48eccb83db fix(idl_gen_ts): bool to number conversion in mutable API (#8677)
Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-09-11 08:36:15 -07:00
Peter Petrov
3c0511fa6a [C#] Added ToSizedArrayPadded(int padLeft, int padRight) to ByteBuffers to avoid unnecessary copying. (#8658)
* Added ToSizedArrayPadded(int padLeft, int padRight) + ToArrayPadded(pos, len, padLeft, padRight) to the byteBuffers.
This is for API completion and to avoid unnecessary copy when framing my packets. I needed this to create a flat buffer with space in front of it for header / metadata.

* Fix indentation

---------

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-09-09 11:38:15 -07:00
bigjt
82396fa0fe [C#] Improve Span<> utilization (#8588)
There are a couple instances where the ByteBuffer's Span property was accessed in a loop.
 + Extracted the use of the property outside of the loop to save a few cpu cycles.

Access to the allocator's internal buffer isn't exposed as a ReadOnlySpan<byte> from the ByteBuffer
or the FlatBufferBuilder.
 + Added a few convenience functions to access the buffer using a ReadOnlySpan<byte>.

There are a few cases where built in Span extensions can be used to run optimized code.
 + Added the use of Span.Fill() and ReadOnlySpan.SequenceCompareTo to replace existing loops.

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-28 16:06:18 -07:00
Curt Hagenlocher
a6b337f803 Add bounds checking to a method where it was missing (#8673)
Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-28 16:06:03 -07:00
TorsteinTenstadNorsonic
35230bd70c [C#] Fix union verifier (#8593)
* [C#] Add test verifying unions

* [C#] Fix verifying unions

---------

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-28 16:05:42 -07:00
Shashank
deb3d93454 gRPC callbackService support added (#8666)
* grpc callbackService support added

Signed-off-by: shankeleven <shashanksati11@gmail.com>

* tests: regenerate C++ gRPC golden with --grpc-callback-api (CallbackService & async_ reactor APIs); update formatting and method placement

---------

Signed-off-by: shankeleven <shashanksati11@gmail.com>
Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-28 15:49:27 -07:00
Felix
b87d04af8c Bugfix: grpc supress incorrect warning (#8669)
new_p is a local addr but is owned now by slice_
thus the life time does not end at the end of the function

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-28 14:27:31 -07:00
Ville Vesilehto
1e6c851dba fix(go/grpc): avoid panic on short FlatBuffers input (#8684)
* fix(go/grpc): avoid panic on short FlatBuffers input

The gRPC codec read the root UOffsetT without checking input size. On
buffers shorter than SizeUOffsetT, GetUint32 touched data[3] and the
process panics.

Add a simple length check and validate the root offset stays within the
buffer. Return clear errors (insufficient data / invalid root offset)
instead of panicking.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* fix(go/grpc): avoid signed overflow in offset

Keep the bounds check in the unsigned domain (UOffsetT) to avoid
signedness pitfalls.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* chore: clarify comment regarding offset

A full FlatBuffer structure would be:

- uoffset_t: root table offset (4 bytes)
- soffset_t: vtable offset in root table (4 bytes)
- uint16_t: vtable size (2 bytes)
- uint16_t: table size (2 bytes)

In total 12 bytes. We are only validating the data length
before trying to read the uoffset_t, not the full structure.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

---------

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2025-08-28 00:31:57 -07:00
mustiikhalil
6164edf558 Fixes swift windows CI (#8685)
Fixes ci failing to a missing component on the github actions side, and
this is enabled until its fixed from the swiftlylab side

Enables swift ci
2025-08-27 23:49:50 -07:00
Derek Bailey
ef1030ff0b Update build.yml - disable gradle CI failures
Both of this are failing and blocking other non-related PRs, disabling for now.
2025-08-27 23:22:12 -07:00
Derek Bailey
53c8c2ef16 Update build.yml - disable Test Swift Windows
This continually fails and the error message is cryptic enough that I don't know how to fix it without an expert.
2025-08-27 23:11:24 -07:00
Derek Bailey
f83525fe67 Update build.yml - update gradle actions
This follows the recommendation here: https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#general-usage
2025-08-27 22:55:17 -07:00
Derek Bailey
b2cce474ba Update build.yml - use java-version 21
Our CI is broken and this is the error:

```
FAILURE: Build failed with an exception.

* What went wrong:
Gradle requires JVM 17 or later to run. Your build is currently configured to use JVM 11.
```

So updating our java-versions to the latest stable version which is 21 apparently.
2025-08-27 22:41:07 -07:00
Jason
067bfdbde9 Update ts codegen (#8421)
Makes the return type of `static getFullyQualifiedName()` be a string literal instead of just the string type

Update tests

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-08-17 20:19:08 -07:00
Justin Davis
5218e29aa4 Fix: Actually call ValidateOptions (#8665)
* fix: actually call ValidateOptions

* convert error to warning in validateoptions
2025-08-12 15:30:35 -07:00
vzjc
957e09d684 CMakeLists: include(CheckSymbolExists) so check_symbol_exists() will work (#8580)
CMake 3.6 and earlier included this implicitly. Newer versions require
it to be explicit.

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-08-11 23:11:14 -07:00
Chan Wang
af4b99a1d7 Add Rust reflection documentation (#8536)
* Add Rust reflection documentation

* Update rust.md
2025-08-08 10:18:17 -07:00
Isaiah Pettingill
b85b90e346 Fix typo in word JavaScript (#8530)
Noticed this on the site. I'm not sure if you have to change it anywhere else, but this looks like the only place the typo occurs
2025-08-08 10:16:52 -07:00
Nugine
ae3821233c docs: fix broken link in readme (#8656) 2025-08-06 22:06:44 -07:00
Felix
ff9cba2bff Doc fix verifier example code for cpp (#8664) 2025-08-06 13:53:44 -07:00
Felix
1759061908 Remove stray required in docs (#8663) 2025-08-06 13:52:57 -07:00
Sourya Kovvali
34af7fff70 Fix native_type non-native_inline fields, add tests (#8655)
* Fix native_type non-native_inline fields, add tests

* Format

* Add 'native_type_test' and 'native_inline_table_test' to generate_code.py

* Remove '--gen-compare' from native_type_test generation
2025-08-03 15:06:01 -07:00
mustiikhalil
518bf42df8 Fixes misaligned pointer by reading from the buffer instead of loading the memory separately (#8649) 2025-07-29 21:26:30 +00:00
mustiikhalil
575d616e60 [Swift] Moves capacity outside of Storage (#8650)
- Cleans up capacity usage within the lib and moves it outside of the Storage

-  Use overflow operators
2025-07-29 14:21:20 -07:00
Felix
f32a7dcbd2 Bugfix __eq__ for numpy data types (#8646)
* [Python] Sync PythonTest.sh flags with generate_code.py

* [Python] Update generated code to latest flatc version for tests

* [Python] Fix test support for numpy newer than 2.0.0

* [Python] Remove unused variable

* [Python] Fix __eq__ for numpy arrays

* [Python] Run clang-format over the entire file
2025-07-26 10:31:38 -07:00
Alex Băluț
860d645349 Support Rust edition 2024 (#8638)
* Developers intro how to contribute

* Fix Rust code generation for Rust edition 2024

The errors look like:

```
warning[E0133]: call to unsafe function `fbs::flatbuffers::emplace_scalar` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::follow_cast_ref` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::Follow::follow` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::read_scalar_at` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::root_unchecked` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::size_prefixed_root_unchecked` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `fbs::flatbuffers::Table::<'a>::new` is unsafe and requires unsafe block
warning[E0133]: call to unsafe function `std::slice::from_raw_parts` is unsafe and requires unsafe block
```

* Update goldens

Ran `goldens/generate_goldens.py`

* Regenerate code files

Ran `scripts/generate_code.py`
2025-07-25 23:12:52 +00:00
Felix
06a53df0d3 Fix start page: Backwards and Forwards Compatibility (#8645) 2025-07-25 16:06:50 -07:00
Łukasz Kurowski
c526cb640b [Python] Enhance object API __init__ with typed keyword arguments (#8615)
This commit significantly improves the developer experience for the Python Object-Based API by overhauling the generated `__init__` method for `T`-suffixed classes.

Previously, `T` objects had to be instantiated with an empty constructor, and their fields had to be populated manually one by one. This was verbose and not idiomatic Python.

This change modifies the Python code generator (`GenInitialize`) to produce `__init__` methods that are:

1.  **Keyword-Argument-Friendly**: The constructor now accepts all table/struct fields as keyword arguments, allowing for concise, single-line object creation.

2.  **Fully Typed**: The signature of the `__init__` method is now annotated with Python type hints. This provides immediate benefits for static analysis tools (like Mypy) and IDEs, enabling better autocompletion and type checking.

3.  **Correctly Optional**: The generator now correctly wraps types in `Optional[...]` if their default value is `None`. This applies to strings, vectors, and other nullable fields, ensuring strict type safety.

The new approach remains **fully backward-compatible**, as all arguments have default values. Existing code that uses the empty constructor will continue to work without modification.

#### Example of a Generated `__init__`

**Before:**

```python
class KeyValueT(object):
    def __init__(self):
        self.key = None  # type: str
        self.value = None  # type: str
```

**After:**

```python
class KeyValueT(object):
    def __init__(self, key: Optional[str] = None, value: Optional[str] = None):
        self.key = key
        self.value = value
```

#### Example of User Code

**Before:**

```python
# Old, verbose way
kv = KeyValueT()
kv.key = "instrument"
kv.value = "EUR/USD"
```

**After:**

```python
# New, Pythonic way
kv = KeyValueT(key="instrument", value="EUR/USD")
```
2025-07-22 23:57:39 -07:00
mustiikhalil
ca73ff34b7 [Swift] Memory usage fix (#8643)
Allows a complete reset for the underlying memory of the
_InternalByteBuffers within FlatBuffers and FlexBuffers.
2025-07-18 09:37:58 -07:00
Rogério Lino
2e49b3ba60 docs: Fixing typo on PHP sample (#8566) 2025-07-17 19:42:14 +00:00
Felix
f830c47d68 [Python] Avoid double flatbuffers include in pyi files (#8626) 2025-07-17 12:37:19 -07:00
Emma
501810f4d1 Fix JavaScript typo in mkdocs.yml (#8515) 2025-07-17 17:53:12 +00:00
Felix
1047d7ec13 Fix Enum type definition (#8624)
Using the : syntax leads to non member attributes.

> If an attribute is defined in the class body with a type annotation
> but with no assigned value, a type checker should assume this is a non-member attribute

```
class Pet(Enum):
    genus: str  # Non-member attribute
    species: str  # Non-member attribute

    CAT = 1  # Member attribute
    DOG = 2  # Member attribute
```

https://typing.python.org/en/latest/spec/enums.html#defining-members
2025-07-16 12:22:45 -07:00
mustiikhalil
07c2eb5fe7 Moves away from @_exported import to add the import in the generated code (#8637) 2025-07-16 12:07:08 -07:00
Felix
c7b9dc83f5 [Python] Avoid include own type (#8625)
This prevents the include of the type defined in the pyi,
otherwise this leads to error message like this:
error: Name XYZ already defined (possibly by an import)  [no-redef]
2025-07-15 11:20:09 -07:00
Gio
4c9079e31b Update logo path (#8602) 2025-07-14 16:09:05 -07:00
Felix
64e5252b4e Fix typo in code comment (#8549) 2025-07-07 12:03:14 -07:00
Dylan Gallagher
00c30807ff Fixed typo in quick_start.md (#8592) 2025-07-07 12:02:40 -07:00
Felix
c15fe421ba Use correct default type for str (#8623)
* [Python] Use correct type for str with None

Otherwise mypy will correctly flag code like this

def __init__(self):
  self.fooBar = None  # type: Optional[str]

error: Incompatible types in assignment (expression has type "None", variable has type "str")

* [Python] Make list type optional as they can contain None
2025-07-04 23:47:36 +00:00
Felix
6b251aa1cf Bugfix/new decode flag (#8634)
* Add docs for new python-decode-obj-api-strings flag

* Fix generate_code by adding missing s to flag
2025-07-04 16:46:28 -07:00
mustiikhalil
6fe8afb3b6 [CI] Moves swift actions to use next (#8632)
* Moves to use swift-actions@next until final release is out

* Migrates to vapor that uses swiftly actions

* Trying to use windows 2022
2025-07-01 13:46:06 -07:00
Truman Mulholland
00eec2445b [TS] Fix relative paths for exports (#8517)
Fixes an issue where exports were using incorrect relative paths for
>=3 namespace levels. This is fixed by making the starting range of the
namespace components relative to the amount of components.

Co-authored-by: Björn Harrtell <bjornharrtell@users.noreply.github.com>
2025-07-01 08:38:02 -07:00
mustiikhalil
b8db3a9a6a Adds windows swift support (#8622)
Adding support for windows requires the code generations
to add a compiler statement to completely ignore GRPC code
generation on windows

Cleanup the project to use the main Package.swift to run tests
instead of having it separate and includes the imports for GRPC
within it.

Adds windows swift ci
2025-06-30 05:45:48 -07:00
Seth Raymond
75556437cc Decode bytes to strings in Python Object API (#8551) 2025-06-29 01:40:10 -07:00
Felix
31beb0fb2f Bugfix: grpc python code generation location and file suffix (#8359)
* clang-format

* [Python] Replace . with _ in grpc filename suffix

Having filenames with . like `file.fb.grcp`
is not great for Python. Since dots are used for namespaces.
Replacing all of them with _ eg suffix `foo.bar.baz` will become
`foo_bar_baz`.

Restoring the previous default `_fb` suffix.

* [Python] Use namespace in path

This fixes a regression introduced with:
fb9afbafc7
And generates the grpc file in the namespace folder again.

* Sync commandline docs with web docs
2025-06-24 22:52:40 -07:00
Aaron Barany
dfd92124aa Avoid outputting Python files for already generated types (#8500)
This may overwrite types that have already been generated and can create
unwanted empty files. Fixes #8490
2025-06-23 12:00:37 -07:00
Björn Harrtell
a2916d37e7 [TS] Upgrade deps (#8620) 2025-06-22 08:59:42 -07:00
mustiikhalil
5a95b7b6bc [Swift] Flexbuffers native swift port (#8577)
* Offical Swift port for FlexBuffers

This is the offical port for FlexBuffers within
swift, and it introcudes a Common Module where code
is shared between flatbuffers and flexbuffers.

Writing most supported values like maps, vectors,
nil and scalars into a flexbuffer buffer. And includes
tests to verify that its similar to cpp

* Reading a flexbuffer

Implementing reading from a flexbuffer, enabling
most of the buffers features, like most types, maps, vectors,
typedvectors, and fixedtypedvectors.

Currently, if an offset/object cant be read we default to a swift
nil instead of the default flexbuffers 'null' with all values.

* Fixes bazel breaking due to new project structure

Address warnings within the library

* Adds comment on why we added the code & properly enforce the amout of bytes needed
2025-06-22 08:36:38 +02:00
Björn Harrtell
595ac94a6a [TS] Enum value default null (#8619)
* [TS] Enum value default null

* Re-gen
2025-06-21 22:25:56 -07:00
Adam Oleksy
5822c1c8dd Fix dereference operator of VectorIterator to structures (#8425)
For Vector or Array of structures the dereference operator of an
iterator returns the pointer to the structure. However, IndirectHelper,
which is used in the implementation of this operator, is instantiated
in the way that the IndirectHelper::Read returns structure by value.

This is because, Vector and Array instantiate IndirectHelper with
const T*, but VectorIterator instantiates IndirectHelper with T. There
are three IndirectHelper template definition: first for T, second for
Offset<T> and the last one for const T*. Those have different
IndirectHelper:Read implementations and (more importantly) return type.
This is the reason of mismatch in VectorIterator::operator* between
return type declaration and what was exactly returned.

That is, for Array<T,...> where T is scalar the VectorIterator is
instantiated as VectorIterator<T, T>, dereference operator returns T
and its implementation uses IndirectHelper<T> which Read function
returns T.
When T is not scalar, then VectorIterator is instantiated as
VectorIterator<T, const T *>, dereference operator returns const T * and
its implementation uses IndirectHelper<T> which Read function returns T.

The fix is done as follows:
* implement type trait is_specialization_of_Offset and
 is_specialization_of_Offset64,
* change partial specialization of IndirectHelper with const T * that
 it is instantiated by T and enabled only if T is not scalar and not
 specialization of Offset or Offset64,
* remove type differentiation (due to scalar) from Array..

The above makes the IndirectHelper able to correctly instantiate itself
basing only on T. Thus, the instantiation in VectorIterator correctly
instantiate IndirectHelper::Read function, especially the return type.
2025-05-17 22:01:09 -07:00
Maurice Sotzny
609c72ca1a [C++] Fixes #8446 (#8447)
Fixes access to union members when generating code with options "--cpp-field-case-style upper" and "--gen-object-api"

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
2025-04-14 08:54:10 -07:00
mustiikhalil
bd1b2d0baf [Swift] Adds new API to reduce memory copying within swift (#8484)
* Adds new API to reduce memory copying within swift

Adds new storage container _InternalByteBuffer which
will be holding the data that will be created within the swift
lib, however reading data will be redirected to ByteBuffer, which
should be able to handle all types of data that swift provide without
the need to copy the data itself. This is due to holding a reference to
the data.

Replaces assumingMemoryBinding with bindMemory which is safer

Adds function that provides access to a UnsafeBufferPointer for
scalars and NativeStructs within swift

Updates docs

Suppress compilation warnings by replacing var with let

Using overflow operators within swift to improve performance

Adds tests for GRPC message creation from a retained _InternalByteBuffer
2025-03-18 07:48:39 +01:00
Derek Bailey
1c514626e8 FlatBuffers Version 25.2.10 2025-02-10 20:25:03 -08:00
Derek Bailey
820a7f277f Remove old documentation 2025-02-10 20:13:39 -08:00
Marcel
396c3f56df Upgrade dependencies (#8516)
As rules_swift bumped the compatibility level, this is required if any dependent repo wants to use the newer version.
2025-02-05 09:01:46 -08:00
mustiikhalil
c49e81d6ec Adds swift 6 to the build matrix (#8414)
Bump min version of swift to be 5.9
2025-02-04 09:11:46 -08:00
Marcin Radomski
a285e7ef1a Rust reflection: simplify dependencies, fix Android build compatibility (#8512)
* flatbuffers Rust reflection: replace num with num-traits

num crate is a wrapper over num-traits and a few other crates, that
reexports the APIs from all of them. We only need num-traits.

Signed-off-by: Marcin Radomski <dextero@google.com>

* Rust reflection: drop dependency on stdint crate

We only use it to get intmax_t for deriving alignment, which is an alias
for `core::ffi::c_long` [1]. We can use that directly instead.

[1] https://docs.rs/stdint/1.0.0/stdint/type.intmax_t.html

Signed-off-by: Marcin Radomski <dextero@google.com>

* Rust reflection: drop dependency on escape_string crate

It's used to format a string used for debugging only, so we might as
well use the builtin Debug representation of a string.

Signed-off-by: Marcin Radomski <dextero@google.com>

* Rust codegen: add derives on generated bitflags

Otherwise it limits the use of structs generated for reflection.fbs
in Rust reflection API.

Signed-off-by: Marcin Radomski <dextero@google.com>

* Rust flatbuffers: update bitflags dependency to 2.8

Signed-off-by: Marcin Radomski <dextero@google.com>

* Rust codegen: use bitflags v2 API for converting from bits

from_bits_unchecked was replaced with safe from_bits_retain.

Signed-off-by: Marcin Radomski <dextero@google.com>

* Regenerate Rust code after idl change

Signed-off-by: Marcin Radomski <dextero@google.com>

* Regenerate reflection_generated.rs

With flatc --rust ../../../reflection/reflection.fbs

Signed-off-by: Marcin Radomski <dextero@google.com>

* ts/BUILD.bazel: add missing import

Found by Buildifire presubmit:

  Function "sh_binary" is not global anymore and needs to be loaded from
  "@rules_shell//shell:sh_binary.bzl".

Signed-off-by: Marcin Radomski <dextero@google.com>

* Update expected value in generated_code_debug_prints_correctly test

In bitflags v2, the debug string representation of enum values is
different than it was in v1:
  Blue -> Color(Blue)
  (empty) -> LongEnum(0x0)

This change adjusts the expected test value.

Signed-off-by: Marcin Radomski <dextero@google.com>

* Fix tests build on Swift 5.8

grpc-swift 1.4.1 depends on swift-nio-ssl 2.14.0+ [1]. swift-nio-ssl 2.29.1
published on 2025-01-30, introduced some code [2] that uses a "switch
expression syntax" supported since Swift 5.9 [3]. Attempts to compile it with
Swift 5.8 cause build errors.

swift-nio-ssl project doesn't seem to support Swift 5.8. A commit from
2024-10-29 removes a "deprecated reference to a Swift 5.8 pipeline" [4].

swift-nio-ssl 2.29.0 is the last version that can be compiled with Swift
5.8. This commit pins it to that exact version.

[1] 66e27d7e84/Package.swift (L33)
[2] 3cb4d5ad12 (diff-bc1db1321ff689c2819245dcce1a3080554f0fc13f81b8d326c97e7d42717c8fR54)
[3] https://github.com/swiftlang/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md
[4] 8a6b89d9a4

---------

Signed-off-by: Marcin Radomski <dextero@google.com>
Co-authored-by: Marcin Radomski <dextero@google.com>
2025-02-04 08:40:31 -08:00
Derek Bailey
0312061985 FlatBuffers Version 25.1.24 2025-01-24 16:36:11 -08:00
Taiju Tsuiki
9f94ceedbc [C++] Avoid adding semicolon after a statement (#8488)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2025-01-24 11:00:18 -08:00
Marcel
bcd2b9d039 Add Bazel docs (#8510) 2025-01-24 10:57:52 -08:00
Marcel
82fefbf252 Remove Bazel WORKSPACE setup. (#8509) 2025-01-24 18:16:10 +00:00
Sebastian Barfurth
65e49faf76 Bump the versions of all aspect Bazel dependencies (#8508)
* bump all aspect dependency versions to latest

* add workspace file to test bazel repo
2025-01-24 10:09:22 -08:00
Marcel
50be3cfe8c Test external modules explicitly in CI (#8507)
This setup is much simpler than calling Bazel from within Bazel
and making sure files and flags are set up correctly.

Co-authored-by: Derek Bailey <derekbailey@google.com>
2025-01-23 23:04:06 +00:00
Marcel
026c243dc5 Add support for Bazel 7 and 8 in Bazel CI (#8505)
* Add missing file to filegroup for bazel integration tests

Fixup after a9257b6963.

* Align versions in bazel_respository_test_dir with root

* Update XCode version to 15.2

This is the oldest available version.

* Add WORKSPACE.bzlmod

* Add support for Bazel 7

* Add support for Bazel 8 in CI
2025-01-23 14:59:14 -08:00
Marcel
a9257b6963 Fix npm bzlmod (#8506)
* Restrict visibility of exported file

* Align npm_translate_lock attrs

* Remove defs_bzl_filename attr

* Align root_package with pnpm-lock.yaml location

Use a symlink to avoid copying the file.
2025-01-23 21:01:31 +00:00
Marcel
fceafd438d Improve Bazel CI (#8502)
* Update Buildkite Bazel CI

Restructure presubmit.yml to support matrix.

* Remove testing Ubuntu 18.04

The available LLVM 6.0 is too old to support std::filesystem.

* Add testing in Ubuntu 22.04

* Use Bazel version 6.5.0 in integration test
2025-01-23 12:10:27 -08:00
Marcel
33a15d63cf Fix reflection.fbs import path (#8499)
We need to copy the .fbs files into the package used for .bfbs files.
This is necessary as flatc doesn't provide support to specify the full
output file name for an .fbs file in a different folder.
I tried OUTPUT_FILE env var but this doesn't seem to be honored by
flatc.
2025-01-23 19:43:23 +00:00
Marcel
ad6d6638f3 Fix Bzlmod (#8503)
* Fix Bzlmod npm repo name

* Fix Bazel integration tests with Bzlmod
2025-01-23 08:52:48 -08:00
Derek Bailey
69ac6a712d Add bazel ci (#8497) 2025-01-22 13:41:45 -08:00
Marcel
4b69b27d43 Also use rules_bazel_bazel_integration_test dependency with Bzlmod (#8498)
* Also use rules_bazel_bazel_integration_test dependency with Bzlmod

* Update versions
2025-01-22 08:22:53 -08:00
Derek Bailey
9318c6c981 Update Evolution doc 2025-01-21 21:28:32 -08:00
1299 changed files with 95381 additions and 78171 deletions

View File

@@ -1,25 +1,16 @@
---
buildifier: latest
bazel: 6.4.0
platforms:
ubuntu1804:
matrix:
bazel:
- 7.x
- 8.x
tasks:
verify_ubuntu2004:
platform: ubuntu2004
bazel: ${{ bazel }}
environment:
CC: clang
SWIFT_VERSION: "5.8"
SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION"
PATH: "$PATH:$SWIFT_HOME/usr/bin"
shell_commands:
- "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME"
- "mkdir $SWIFT_HOME"
- "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu1804/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu18.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME"
build_targets:
- "//..."
test_targets:
- "//..."
ubuntu2004:
environment:
CC: clang
SWIFT_VERSION: "5.8"
SWIFT_VERSION: "5.10"
SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION"
PATH: "$PATH:$SWIFT_HOME/usr/bin"
shell_commands:
@@ -30,8 +21,38 @@ platforms:
- "//..."
test_targets:
- "//..."
macos:
xcode_version: "14.3"
verify_ubuntu2204:
platform: ubuntu2204
bazel: ${{ bazel }}
environment:
CC: clang
SWIFT_VERSION: "5.10"
SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION"
PATH: "$PATH:$SWIFT_HOME/usr/bin"
shell_commands:
- "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME"
- "mkdir $SWIFT_HOME"
- "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2204/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu22.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME"
build_targets:
- "//..."
test_targets:
- "//..."
test_module_cpp:
platform: ubuntu2204
bazel: ${{ bazel }}
working_directory: tests/bazel_repository_test_dir
build_targets:
- "//..."
test_module_ts:
platform: ubuntu2204
bazel: ${{ bazel }}
working_directory: tests/ts/bazel_repository_test_dir
test_targets:
- "//..."
verify_macos:
platform: macos
bazel: ${{ bazel }}
xcode_version: "15.2"
build_targets:
- "//:flatbuffers"
- "//:flatc"

View File

@@ -1 +1,5 @@
ts/node_modules
# Test workspaces
tests/bazel_repository_test_dir
tests/ts/bazel_repository_test_dir

View File

@@ -9,4 +9,10 @@ common --action_env=JAVA_HOME=../bazel_tools/jdk
# Workaround "Error: need --enable_runfiles on Windows for to support rules_js"
common:windows --enable_runfiles
# Swift is not required on Windows
common:windows --deleted_packages=swift
common:windows --deleted_packages=swift
# Ignore warnings in external dependencies
build --per_file_copt=external/.*@-Wno-everything --host_per_file_copt=external/.*@-Wno-everything
# Honor the setting of `skipLibCheck` in the tsconfig.json file.
common --@aspect_rules_ts//ts:skipLibCheck=honor_tsconfig
# Use "tsc" as the transpiler when ts_project has no `transpiler` set.
common --@aspect_rules_ts//ts:default_to_tsc_transpiler

View File

@@ -1,13 +1,5 @@
---
Language: Cpp
BasedOnStyle: Google
DerivePointerAlignment: false
PointerAlignment: Right
IndentPPDirectives: AfterHash
Cpp11BracedListStyle: false
AlwaysBreakTemplateDeclarations: false
AllowShortCaseLabelsOnASingleLine: true
SpaceAfterTemplateKeyword: false
AllowShortBlocksOnASingleLine: true
...

View File

@@ -1,13 +0,0 @@
/* eslint-env node */
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
]
};

5
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default owner
* @dbaileychess derekbailey@google.com
# Prevent modification of this file
.github/CODEOWNERS @dbaileychess derekbailey@google.com

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

146
.github/labeler.yml vendored
View File

@@ -5,93 +5,133 @@
#
# See .github/workflows/label.yml for Github Action workflow script
c#:
- '**/*.cs'
- net/**/*
- tests/FlatBuffers.Test/**/*
- tests/FlatBuffers.Benchmarks/**/*
- src/idl_gen_csharp.cpp
"c#":
- changed-files:
- any-glob-to-any-file:
- '**/*.cs'
- 'net/**/*'
- 'tests/FlatBuffers.Test/**/*'
- 'tests/FlatBuffers.Benchmarks/**/*'
- 'src/idl_gen_csharp.cpp'
swift:
- '**/*.swift'
- swift/**/*
- tests/swift/**
- src/idl_gen_swift.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.swift'
- 'swift/**/*'
- 'tests/swift/**'
- 'src/idl_gen_swift.cpp'
nim:
- '**/*.nim'
- nim/**/*
- src/idl_gen_nim.cpp
- src/bfbs_gen_nim.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.nim'
- 'nim/**/*'
- 'src/idl_gen_nim.cpp'
- 'src/bfbs_gen_nim.cpp'
javascript:
- '**/*.js'
- src/idl_gen_ts.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.js'
- 'src/idl_gen_ts.cpp'
typescript:
- '**/*.ts'
- src/idl_gen_ts.cpp
- grpc/flatbuffers-js-grpc/**/*.ts
- changed-files:
- any-glob-to-any-file:
- '**/*.ts'
- 'src/idl_gen_ts.cpp'
- 'grpc/flatbuffers-js-grpc/**/*.ts'
golang:
- '**/*.go'
- src/idl_gen_go.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.go'
- 'src/idl_gen_go.cpp'
python:
- '**/*.py'
- src/idl_gen_python.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.py'
- 'src/idl_gen_python.cpp'
java:
- '**/*.java'
- src/idl_gen_java.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.java'
- 'src/idl_gen_java.cpp'
kotlin:
- '**/*.kt'
- src/idl_gen_kotlin.cpp
- src/idl_gen_kotlin_kmp.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.kt'
- 'src/idl_gen_kotlin.cpp'
- 'src/idl_gen_kotlin_kmp.cpp'
lua:
- '**/*.lua'
- lua/**/*
- src/bfbs_gen_lua.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.lua'
- 'lua/**/*'
- 'src/bfbs_gen_lua.cpp'
lobster:
- '**/*.lobster'
- src/idl_gen_lobster.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.lobster'
- 'src/idl_gen_lobster.cpp'
php:
- '**/*.php'
- src/idl_gen_php.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.php'
- 'src/idl_gen_php.cpp'
rust:
- '**/*.rs'
- rust/**/*
- src/idl_gen_rust.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.rs'
- 'rust/**/*'
- 'src/idl_gen_rust.cpp'
dart:
- '**/*.dart'
- src/idl_gen_dart.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.dart'
- 'src/idl_gen_dart.cpp'
c++:
- '**/*.cc'
- '**/*.cpp'
- '**/*.h'
"c++":
- changed-files:
- any-glob-to-any-file:
- '**/*.cc'
- '**/*.cpp'
- '**/*.h'
json:
- '**/*.json'
- src/idl_gen_json_schema.cpp
- changed-files:
- any-glob-to-any-file:
- '**/*.json'
- 'src/idl_gen_json_schema.cpp'
codegen:
- src/**/*
- changed-files:
- any-glob-to-any-file:
- 'src/**/*'
documentation:
- docs/**/*
- '**/*.md'
- changed-files:
- any-glob-to-any-file:
- 'docs/**/*'
- '**/*.md'
CI:
- '.github/**/*'
- '.bazelci/**/*'
- changed-files:
- any-glob-to-any-file:
- '.github/**/*'
- '.bazelci/**/*'
grpc:
- grpc/**/*
- src/idl_gen_grpc.cpp
- changed-files:
- any-glob-to-any-file:
- 'grpc/**/*'
- 'src/idl_gen_grpc.cpp'

View File

@@ -30,7 +30,7 @@ jobs:
cxx: [g++-13, clang++-18]
fail-fast: false
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_STATIC_FLATC=ON .
- name: build
@@ -42,7 +42,7 @@ jobs:
chmod +x flatc
./flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Linux flatc binary ${{ matrix.cxx }}
path: flatc
@@ -51,7 +51,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: zip Linux.flatc.binary.${{ matrix.cxx }}.zip flatc
- name: Release zip file
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Linux.flatc.binary.${{ matrix.cxx }}.zip
@@ -68,7 +68,7 @@ jobs:
name: Build Linux with -DFLATBUFFERS_NO_FILE_TESTS
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: CXX=clang++-18 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_CXX_FLAGS="-DFLATBUFFERS_NO_FILE_TESTS" .
- name: build
@@ -80,7 +80,7 @@ jobs:
name: Build Linux with out-of-source build location
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: make build directory
run: mkdir build
- name: cmake
@@ -112,7 +112,7 @@ jobs:
std: 23
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: >
CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles"
@@ -129,18 +129,18 @@ jobs:
build-cpp-std:
name: Build Windows C++
runs-on: windows-2019
runs-on: windows-2022
strategy:
matrix:
std: [11, 14, 17, 20, 23]
fail-fast: false
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: cmake
run: >
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release
cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
-DFLATBUFFERS_STRICT_MODE=ON
-DFLATBUFFERS_CPP_STD=${{ matrix.std }}
-DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}}
@@ -157,20 +157,20 @@ jobs:
contents: write
outputs:
digests: ${{ steps.hash.outputs.hashes }}
name: Build Windows 2019
runs-on: windows-2019
name: Build Windows 2022
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: cmake
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: test
run: Release\flattests.exe
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Windows flatc binary
path: Release\flatc.exe
@@ -179,7 +179,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: move Release/flatc.exe . && Compress-Archive flatc.exe Windows.flatc.binary.zip
- name: Release binary
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Windows.flatc.binary.zip
@@ -191,25 +191,24 @@ jobs:
build-dotnet-windows:
name: Build .NET Windows
runs-on: windows-2022-64core
runs-on: windows-2022
strategy:
matrix:
configuration: [
'',
'-p:UnsafeByteBuffer=true',
# Fails two tests currently.
#'-p:EnableSpanT=true,UnsafeByteBuffer=true'
'-p:EnableSpanT=true,UnsafeByteBuffer=true'
]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v4.2.0
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd tests\FlatBuffers.Test
dotnet new sln --force --name FlatBuffers.Test
dotnet new sln --force --name FlatBuffers.Test --format sln
dotnet sln FlatBuffers.Test.sln add FlatBuffers.Test.csproj
dotnet build -c Release ${{matrix.configuration}} FlatBuffers.Test.sln
- name: Run net6.0
@@ -228,9 +227,9 @@ jobs:
outputs:
digests: ${{ steps.hash.outputs.hashes }}
name: Build Mac (for Intel)
runs-on: macos-latest-large
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
@@ -247,7 +246,7 @@ jobs:
chmod +x Release/flatc
Release/flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Mac flatc binary Intel
path: Release/flatc
@@ -256,7 +255,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc
- name: Release binary
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: MacIntel.flatc.binary.zip
@@ -273,7 +272,7 @@ jobs:
name: Build Mac (universal build)
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
@@ -290,7 +289,7 @@ jobs:
chmod +x Release/flatc
Release/flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Mac flatc binary Universal
path: Release/flatc
@@ -299,7 +298,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc
- name: Release binary
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Mac.flatc.binary.zip
@@ -310,14 +309,17 @@ jobs:
build-android:
name: Build Android (on Linux)
if: false #disabled due to continual failure
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '11'
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v5
- name: set up flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
@@ -334,7 +336,7 @@ jobs:
matrix:
cxx: [g++-13, clang++-18]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
- name: Generate
@@ -344,13 +346,13 @@ jobs:
build-generator-windows:
name: Check Generated Code on Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: cmake
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: Generate
@@ -365,13 +367,13 @@ jobs:
matrix:
cxx: [g++-13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
- name: Run benchmarks
run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}}
- name: Upload benchmarks results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Linux flatbenchmark results ${{matrix.cxx}}
path: benchmarks/results_${{matrix.cxx}}
@@ -380,29 +382,24 @@ jobs:
name: Build Java
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: test
working-directory: java
run: mvn test
build-kotlin-macos:
name: Build Kotlin MacOS
runs-on: macos-13
runs-on: macos-15
steps:
- name: Checkout
uses: actions/checkout@v3
# Force Xcode 14.3 since Xcode 15 doesnt support older versions of
# kotlin. For Xcode 15, kotlin should be bumpped to 1.9.10
# https://stackoverflow.com/a/77150623
# For now, run with macos-13 which has this 14.3 installed:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
- name: Set up Xcode version
run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
- uses: gradle/wrapper-validation-action@v1.0.5
- uses: actions/setup-java@v3
uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '11'
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v5
- name: Build flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -414,15 +411,18 @@ jobs:
build-kotlin-linux:
name: Build Kotlin Linux
if: false #disabled due to continual failure
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/setup-java@v3
uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '11'
- uses: gradle/wrapper-validation-action@v1.0.5
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v5
- name: Build flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -439,16 +439,16 @@ jobs:
name: Build Rust Linux
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: test
working-directory: tests
run: bash RustTest.sh
build-rust-windows:
name: Build Rust Windows
runs-on: windows-2022-64core
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: test
working-directory: tests
run: ./RustTest.bat
@@ -457,7 +457,7 @@ jobs:
name: Build Python
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -469,7 +469,7 @@ jobs:
name: Build Go
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -481,7 +481,7 @@ jobs:
name: Build PHP
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -492,63 +492,74 @@ jobs:
sh phpUnionVectorTest.sh
build-swift:
name: Build Swift
name: Test Swift Linux
strategy:
matrix:
swift: ["5.8", "5.9", "5.10"]
# Only 22.04 has swift at the moment https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md?plain=1#L30
runs-on: ubuntu-22.04
swift: ["6.0", "6.1", "6.2"]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- uses: swift-actions/setup-swift@v2
with:
swift-version: ${{ matrix.swift }}
- name: Get swift version
run: swift --version
- name: test
working-directory: tests/swift/tests
run: |
swift build --build-tests
swift test
run: swift test
build-swift-windows:
name: Test swift windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: SwiftyLab/setup-swift@latest
with:
swift-version: '6.1'
- run: swift build
- run: swift test
build-swift-wasm:
name: Build Swift Wasm
name: Test Swift Wasm
runs-on: ubuntu-24.04
container:
image: ghcr.io/swiftwasm/carton:0.20.1
steps:
- uses: actions/checkout@v3
- uses: bytecodealliance/actions/wasmtime/setup@v1
- uses: swiftwasm/setup-swiftwasm@v1
- uses: actions/checkout@v6
- uses: swift-actions/setup-swift@v2
with:
swift-version: "wasm-6.0.2-RELEASE"
swift-version: 6.2.1
- uses: bytecodealliance/actions/wasmtime/setup@v1
- name: Install Swift SDK
run: swift sdk install https://download.swift.org/swift-6.2.1-release/wasm-sdk/swift-6.2.1-RELEASE/swift-6.2.1-RELEASE_wasm.artifactbundle.tar.gz --checksum 482b9f95462b87bedfafca94a092cf9ec4496671ca13b43745097122d20f18af
- name: Test
working-directory: tests/swift/Wasm.tests
run: swift run carton test
run: |
swift sdk list
swift build --build-tests --swift-sdk swift-6.2.1-RELEASE_wasm
wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest --testing-library swift-testing
build-ts:
name: Build TS
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm
run: npm install -g pnpm
- name: deps
run: yarn
run: pnpm i
- name: compile
run: yarn compile
run: pnpm compile
- name: test
working-directory: tests/ts
run: |
yarn global add esbuild
python3 TypeScriptTest.py
build-dart:
name: Build Dart
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
with:
sdk: stable
@@ -563,11 +574,11 @@ jobs:
name: Build Nim
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- uses: jiro4989/setup-nim-action@v1
- uses: jiro4989/setup-nim-action@v2
- name: install library
working-directory: nim
run: nimble -y develop && nimble install
@@ -575,6 +586,26 @@ jobs:
working-directory: tests/nim
run: python3 testnim.py
bazel:
name: Bazel
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
# Explicitly use 8.5.1 until we can update or https://github.com/actions/runner-images/issues/13564 is fixed.
- name: Set env
run: >
echo "USE_BAZEL_VERSION=8.5.1" >> $GITHUB_ENV
- name: bazel build
run: >
bazel build
//:flatc
//:flatbuffers
//tests:flatbuffers_test
- name: bazel test
run: >
bazel test
//tests:flatbuffers_test
release-digests:
if: startsWith(github.ref, 'refs/tags/')
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
@@ -606,8 +637,7 @@ jobs:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.1
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: "${{ needs.release-digests.outputs.digests }}"
upload-assets: true # Optional: Upload to a new release
compile-generator: true # Workaround for https://github.com/slsa-framework/slsa-github-generator/issues/1163

View File

@@ -16,16 +16,16 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache

View File

@@ -19,6 +19,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@ee18d5d34efd9b4f7dafdb0e363cb688eb438044 # 4.1.0
- uses: actions/labeler@v6
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -27,7 +27,7 @@ jobs:
language: c++
fuzz-seconds: 60
- name: Upload Crash
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts

View File

@@ -12,8 +12,8 @@ jobs:
name: Publish NPM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
@@ -29,19 +29,19 @@ jobs:
run:
working-directory: ./python
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Install Dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install setuptools wheel twine
python3 -m pip install build twine
- name: Build
run: |
python3 setup.py sdist bdist_wheel
python3 -m build .
- name: Upload to PyPi
run: |
@@ -57,8 +57,8 @@ jobs:
run:
working-directory: ./net/flatbuffers
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Build
@@ -80,10 +80,10 @@ jobs:
run:
working-directory: ./java
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Set up Maven Central Repository
uses: actions/setup-java@v3
uses: actions/setup-java@v5
with:
java-version: '11'
distribution: 'adopt'
@@ -108,9 +108,9 @@ jobs:
run:
working-directory: ./kotlin
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Set up Maven Central Repository
uses: actions/setup-java@v3
uses: actions/setup-java@v5
with:
java-version: '11'
distribution: 'adopt'
@@ -133,7 +133,7 @@ jobs:
name: Publish crates.io
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- uses: actions-rs/toolchain@v1
with:
toolchain: stable

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v7.0.0
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 500

5
.gitignore vendored
View File

@@ -156,4 +156,7 @@ kotlin/**/generated
MODULE.bazel.lock
# Ignore the generated docs
docs/site
docs/site
# Ignore generated files
*.fbs.h

View File

@@ -32,7 +32,6 @@ filegroup(
".npmrc",
"BUILD.bazel",
"MODULE.bazel",
"WORKSPACE",
"build_defs.bzl",
"package.json",
"pnpm-lock.yaml",

View File

@@ -4,6 +4,34 @@ All major or breaking changes will be documented in this file, as well as any
new features that should be highlighted. Minor fixes or improvements are not
necessarily listed.
## [25.12.19] (December 19 2025)(https://github.com/google/flatbuffers/releases/tag/v25.12.19)
* [C++] Default emptry vector support (#8870)
* [C++] Add --gen-absl-hash option (#8868)
* [Kotlin] Upgrade to MacOS 15 (#8845)
* [C++] Fix vector of table with naked ptrs (#8830)
* [Python] Optimize Offset/Pad/Prep (#8808)
* Implement `--file-names-only` (#8788)
* [C++] Fix size verifer (#8740)
## [25.9.23] (September 23 2025)(https://github.com/google/flatbuffers/releases/tag/v25.9.23)
* flatc: `--grpc-callback-api` flag generates C++ gRPC Callback API server `CallbackService` skeletons AND client native callback/async stubs (unary + all streaming reactor forms) (opt-in, non-breaking, issue #8596).
* Swift - Adds new API to reduce memory copying within swift (#8484)
* Rust - Support Rust edition 2024 (#8638)
* [C++] - Use the Google Style for clang-format without exceptions (#8706)
## [25.2.10] (February 10 2025)(https://github.com/google/flatbuffers/releases/tag/v25.2.10)
* Removed the old documentation pages. The new one is live at https://flatbuffers.dev
* Swift version 6.0 support (#8414)
## [25.1.24] (January 24 2025)(https://github.com/google/flatbuffers/releases/tag/v25.1.24)
* Mostly related to bazel build support.
* Min bazel supported is now 7 or higher, as WORKSPACE files are removed (#8509)
* Minor C++ codegen fix removing extra semicolon (#8488)
## [25.1.21] (January 21 2025)(https://github.com/google/flatbuffers/releases/tag/v25.1.21)
* Rust Full Reflection (#8102)

View File

@@ -305,8 +305,7 @@ function(flatbuffers_generate_headers)
${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS})
add_dependencies(
${FLATBUFFERS_GENERATE_HEADERS_TARGET}
${FLATC}
${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS})
${FLATC_TARGET})
target_include_directories(
${FLATBUFFERS_GENERATE_HEADERS_TARGET}
INTERFACE ${generated_target_dir})

View File

@@ -1,6 +1,6 @@
set(VERSION_MAJOR 25)
set(VERSION_MINOR 1)
set(VERSION_PATCH 21)
set(VERSION_MINOR 12)
set(VERSION_PATCH 19)
set(VERSION_COMMIT 0)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")

View File

@@ -112,6 +112,7 @@ endif()
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
if(NOT WIN32)
include(CheckSymbolExists)
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
if(NOT HAVE_REALPATH)
add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION)
@@ -146,6 +147,8 @@ set(FlatBuffers_Library_SRCS
include/flatbuffers/vector.h
include/flatbuffers/vector_downward.h
include/flatbuffers/verifier.h
src/file_manager.cpp
src/file_name_manager.cpp
src/idl_parser.cpp
src/idl_gen_text.cpp
src/reflection.cpp
@@ -172,9 +175,6 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_grpc.cpp
src/idl_gen_json_schema.cpp
src/idl_gen_swift.cpp
src/file_name_saving_file_manager.cpp
src/file_binary_writer.cpp
src/file_writer.cpp
src/idl_namer.h
src/namer.h
src/flatc.cpp
@@ -218,6 +218,8 @@ set(FlatHash_SRCS
set(FlatBuffers_Tests_SRCS
${FlatBuffers_Library_SRCS}
src/idl_gen_fbs.cpp
tests/default_vectors_strings_test.cpp
tests/default_vectors_strings_test.h
tests/evolution_test.cpp
tests/flexbuffers_test.cpp
tests/fuzz_test.cpp
@@ -234,6 +236,8 @@ set(FlatBuffers_Tests_SRCS
tests/test_builder.h
tests/test_builder.cpp
tests/util_test.cpp
tests/vector_table_naked_ptr_test.h
tests/vector_table_naked_ptr_test.cpp
tests/native_type_test_impl.h
tests/native_type_test_impl.cpp
tests/alignment_test.h
@@ -278,6 +282,8 @@ set(FlatBuffers_GRPCTest_SRCS
tests/test_builder.cpp
grpc/tests/grpctest.cpp
grpc/tests/message_builder_test.cpp
grpc/tests/grpctest_callback_compile.cpp
grpc/tests/grpctest_callback_client_compile.cpp
)
# TODO(dbaileychess): Figure out how this would now work. I posted a question on
@@ -492,28 +498,34 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
endif()
endif()
function(compile_schema SRC_FBS OPT OUT_GEN_FILE)
function(compile_schema SRC_FBS OPT SUFFIX OUT_GEN_FILE)
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
string(REGEX REPLACE "\\.fbs$" "${SUFFIX}.h" GEN_HEADER ${SRC_FBS})
add_custom_command(
OUTPUT ${GEN_HEADER}
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
${OPT}
--filename-suffix ${SUFFIX}
-o "${SRC_FBS_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
DEPENDS flatc ${SRC_FBS}
COMMENT "flatc generation: `${SRC_FBS}` -> `${GEN_HEADER}`"
)
)
set(${OUT_GEN_FILE} ${GEN_HEADER} PARENT_SCOPE)
endfunction()
function(compile_schema_for_test SRC_FBS OPT)
compile_schema("${SRC_FBS}" "${OPT}" GEN_FILE)
compile_schema("${SRC_FBS}" "${OPT}" "_generated" GEN_FILE)
target_sources(flattests PRIVATE ${GEN_FILE})
endfunction()
function(compile_schema_for_test_fbsh SRC_FBS OPT)
compile_schema("${SRC_FBS}" "${OPT}" ".fbs" GEN_FILE)
target_sources(flattests PRIVATE ${GEN_FILE})
endfunction()
function(compile_schema_for_samples SRC_FBS OPT)
compile_schema("${SRC_FBS}" "${OPT}" GEN_FILE)
compile_schema("${SRC_FBS}" "${OPT}" "_generated" GEN_FILE)
target_sources(flatsample PRIVATE ${GEN_FILE})
endfunction()
@@ -534,19 +546,20 @@ if(FLATBUFFERS_BUILD_TESTS)
add_definitions(-DFLATBUFFERS_TEST_PATH_PREFIX=${CMAKE_CURRENT_SOURCE_DIR}/)
# The flattest target needs some generated files
SET(FLATC_OPT --cpp --gen-mutable --gen-object-api --reflect-names)
SET(FLATC_OPT_COMP ${FLATC_OPT};--gen-compare)
SET(FLATC_OPT_COMP --cpp --gen-compare --gen-mutable --gen-object-api --reflect-names)
SET(FLATC_OPT_SCOPED_ENUMS ${FLATC_OPT_COMP};--scoped-enums)
compile_schema_for_test(tests/alignment_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test_fbsh(tests/default_vectors_strings_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/arrays_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT}")
compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed")
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/evolution/v2.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/union_underlying_type_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
compile_schema_for_test(tests/cross_namespace_pack_test.fbs "${FLATC_OPT_COMP}")
if(FLATBUFFERS_CODE_SANITIZE)
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
@@ -568,8 +581,6 @@ if(FLATBUFFERS_BUILD_TESTS)
# Since flatsample has no sources, we have to explicitly set the linker lang.
set_target_properties(flatsample PROPERTIES LINKER_LANGUAGE CXX)
compile_schema_for_samples(samples/monster.fbs "${FLATC_OPT_COMP}")
target_link_libraries(flatsamplebinary PRIVATE $<BUILD_INTERFACE:ProjectConfig> flatsample)
target_link_libraries(flatsampletext PRIVATE $<BUILD_INTERFACE:ProjectConfig> flatsample)

View File

@@ -30,7 +30,7 @@ Some tips for good pull requests:
* Write a descriptive commit message. What problem are you solving and what
are the consequences? Where and what did you test? Some good tips:
[here](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message)
and [here](https://www.kernel.org/doc/Documentation/SubmittingPatches).
and [here](https://www.kernel.org/doc/Documentation/process/submitting-patches.rst).
* If your PR consists of multiple commits which are successive improvements /
fixes to your first commit, consider squashing them into a single commit
(`git rebase -i`) such that your PR is a single commit on top of the current
@@ -40,3 +40,26 @@ Some tips for good pull requests:
# The small print
Contributions made by corporations are covered by a different agreement than
the one above, the Software Grant and Corporate Contributor License Agreement.
# Code
TL/DR
See [how to build flatc](https://flatbuffers.dev/building/).
When making changes, build `flatc` and then re-generate the goldens files to see the effect of your changes:
```
$ cp build/flatc .
$ goldens/generate_goldens.py
```
Re-generate other code files to see the effects of the changes:
```
$ scripts/generate_code.py
```
Run tests with [TestAll.sh](tests/TestAll.sh) in [tests](tests), or directly any of the sub-scripts run by it.
[Format the code](Formatters.md) before submitting a PR.

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'FlatBuffers'
s.version = '25.1.21'
s.version = '25.12.19'
s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
s.description = "FlatBuffers is a cross platform serialization library architected for
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '11.0'
s.osx.deployment_target = '10.14'
s.swift_version = '5.0'
s.swift_version = '5.10'
s.source_files = 'swift/Sources/Flatbuffers/*.swift'
s.pod_target_xcconfig = {
'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES'

View File

@@ -19,4 +19,4 @@ Swift uses swiftformat as it's formatter. Take a look at [how to install here](h
## Typescript
Typescript uses eslint as it's linter. Take a look at [how to install here](https://eslint.org/docs/user-guide/getting-started). Run the following command `eslint ts/** --ext .ts` in the root directory of the project
Typescript uses eslint as it's linter. Take a look at [how to install here](https://eslint.org/docs/user-guide/getting-started). Run the following command `eslint ts/** --ext .ts` in the root directory of the project

View File

@@ -1,62 +1,71 @@
module(
name = "flatbuffers",
version = "24.3.25",
version = "25.12.19",
compatibility_level = 1,
repo_name = "com_github_google_flatbuffers",
)
bazel_dep(
name = "aspect_bazel_lib",
version = "1.40.0",
version = "2.14.0",
)
bazel_dep(
name = "aspect_rules_esbuild",
version = "0.15.0",
version = "0.21.0",
)
bazel_dep(
name = "aspect_rules_js",
version = "1.34.1",
version = "2.3.8",
)
bazel_dep(
name = "aspect_rules_ts",
version = "1.4.5",
version = "3.6.0",
)
bazel_dep(
name = "grpc",
version = "1.48.1",
version = "1.76.0",
repo_name = "com_github_grpc_grpc",
)
bazel_dep(
name = "platforms",
version = "0.0.7",
version = "0.0.11",
)
bazel_dep(
name = "rules_cc",
version = "0.0.9",
version = "0.1.1",
)
bazel_dep(
name = "rules_go",
version = "0.41.0",
version = "0.50.1",
repo_name = "io_bazel_rules_go",
)
bazel_dep(
name = "rules_nodejs",
version = "5.8.3",
version = "6.3.3",
)
bazel_dep(
name = "rules_shell",
version = "0.3.0",
)
bazel_dep(
name = "rules_swift",
version = "1.2.0",
version = "3.1.2",
max_compatibility_level = 3,
repo_name = "build_bazel_rules_swift",
)
bazel_dep(
name = "bazel_skylib",
version = "1.7.1",
)
npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm")
npm.npm_translate_lock(
name = "npm",
name = "flatbuffers_npm",
npmrc = "//:.npmrc",
pnpm_lock = "//:pnpm-lock.yaml",
pnpm_lock = "//ts:pnpm-lock.yaml",
verify_node_modules_ignored = "//:.bazelignore",
)
use_repo(npm, "npm")
use_repo(npm, "flatbuffers_npm")
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
use_repo(node, "nodejs_linux_amd64")
@@ -64,9 +73,3 @@ use_repo(node, "nodejs_linux_amd64")
rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext", dev_dependency = True)
rules_ts_ext.deps()
use_repo(rules_ts_ext, "npm_typescript")
non_module_dependencies = use_extension("//:extensions.bzl", "non_module_dependencies", dev_dependency = True)
use_repo(
non_module_dependencies,
"bazel_linux_x86_64",
)

View File

@@ -1,4 +1,4 @@
// swift-tools-version:5.8
// swift-tools-version:6.0
/*
* Copyright 2020 Google Inc. All rights reserved.
*
@@ -20,17 +20,79 @@ import PackageDescription
let package = Package(
name: "FlatBuffers",
platforms: [
.iOS(.v11),
.iOS(.v12),
.macOS(.v10_14),
],
products: [
.library(
name: "FlatBuffers",
targets: ["FlatBuffers"]),
.library(
name: "FlexBuffers",
targets: ["FlexBuffers"]),
],
dependencies: .dependencies,
targets: [
.target(
name: "FlatBuffers",
dependencies: [],
path: "swift/Sources"),
])
dependencies: ["Common"],
path: "swift/Sources/FlatBuffers",
swiftSettings: .settings),
.target(
name: "FlexBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlexBuffers",
swiftSettings: .settings),
.target(
name: "Common",
path: "swift/Sources/Common",
swiftSettings: .settings),
.testTarget(
name: "FlatbuffersTests",
dependencies: .dependencies,
path: "tests/swift/Tests/Flatbuffers"),
.testTarget(
name: "FlexbuffersTests",
dependencies: ["FlexBuffers"],
path: "tests/swift/Tests/Flexbuffers"),
],
swiftLanguageModes: [.v6])
extension Array where Element == SwiftSetting {
static var settings: [SwiftSetting] {
[.enableUpcomingFeature("ExistentialAny")]
}
}
extension Array where Element == Package.Dependency {
static var dependencies: [Package.Dependency] {
#if os(Windows)
[]
#else
// Test only Dependency
[
.package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.0.0"),
.package(
url: "https://github.com/grpc/grpc-swift-nio-transport.git",
from: "2.0.0"),
]
#endif
}
}
extension Array where Element == PackageDescription.Target.Dependency {
static var dependencies: [PackageDescription.Target.Dependency] {
#if os(Windows)
["FlatBuffers"]
#else
// Test only Dependency
[
.product(name: "GRPCCore", package: "grpc-swift-2"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
"FlatBuffers",
]
#endif
}
}

View File

@@ -1,4 +1,4 @@
![logo](http://google.github.io/flatbuffers/fpl_logo_small.png) FlatBuffers
![logo](https://flatbuffers.dev/assets/flatbuffers_logo.svg) FlatBuffers
===========
![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master)
@@ -34,7 +34,7 @@ maximum memory efficiency. It allows you to directly access serialized data with
```
./flatc --cpp --rust monster.fbs
```
Which generates `monster_generated.h` and `monster_generated.rs` files.
4. Serialize data
@@ -48,7 +48,7 @@ maximum memory efficiency. It allows you to directly access serialized data with
6. Read the data
Use the generated accessors to read the data from the serialized buffer.
It doesn't need to be the same language/schema version, FlatBuffers ensures the data is readable across languages and schema versions. See the [`Rust` example](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.rs#L92-L106) reading the data written by `C++`.
## Documentation

212
WORKSPACE
View File

@@ -1,212 +0,0 @@
workspace(name = "com_github_google_flatbuffers")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "platforms",
sha256 = "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
"https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
],
)
# Import our own version of skylib before other rule sets (e.g. rules_swift)
# has a chance to import an old version.
http_archive(
name = "bazel_skylib",
sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
],
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
http_archive(
name = "build_bazel_rules_apple",
sha256 = "34c41bfb59cdaea29ac2df5a2fa79e5add609c71bb303b2ebb10985f93fa20e7",
url = "https://github.com/bazelbuild/rules_apple/releases/download/3.1.1/rules_apple.3.1.1.tar.gz",
)
load(
"@build_bazel_rules_apple//apple:repositories.bzl",
"apple_rules_dependencies",
)
apple_rules_dependencies()
http_archive(
name = "build_bazel_rules_swift",
sha256 = "a2fd565e527f83fb3f9eb07eb9737240e668c9242d3bc318712efa54a7deda97",
url = "https://github.com/bazelbuild/rules_swift/releases/download/0.27.0/rules_swift.0.27.0.tar.gz",
)
load(
"@build_bazel_rules_swift//swift:repositories.bzl",
"swift_rules_dependencies",
)
swift_rules_dependencies()
load(
"@build_bazel_rules_swift//swift:extras.bzl",
"swift_rules_extra_dependencies",
)
swift_rules_extra_dependencies()
http_archive(
name = "io_bazel_rules_go",
sha256 = "278b7ff5a826f3dc10f04feaf0b70d48b68748ccd512d7f98bf442077f043fe3",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip",
],
)
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies")
go_rules_dependencies()
##### Protobuf
_PROTOBUF_VERSION = "3.15.2"
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-" + _PROTOBUF_VERSION,
urls = [
"https://github.com/protocolbuffers/protobuf/archive/v" + _PROTOBUF_VERSION + ".tar.gz",
],
)
#### Building boring ssl
# Fetching boringssl within the flatbuffers repository, to patch the issue
# of not being able to upgrade to Xcode 14.3 due to buildkite throwing errors
# which was patched in the following below.
# https://github.com/google/flatbuffers/commit/67eb95de9281087ccbba9aafd6e8ab1958d12045
# The patch was copied from the following comment on the same issue within tensorflow
# and fixed to adapt the already existing patch for boringssl.
# https://github.com/tensorflow/tensorflow/issues/60191#issuecomment-1496073147
http_archive(
name = "boringssl",
patch_args = ["-p1"],
patches = ["//grpc:boringssl.patch"],
# Use github mirror instead of https://boringssl.googlesource.com/boringssl
# to obtain a boringssl archive with consistent sha256
sha256 = "534fa658bd845fd974b50b10f444d392dfd0d93768c4a51b61263fd37d851c40",
strip_prefix = "boringssl-b9232f9e27e5668bc0414879dcdedb2a59ea75f2",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
"https://github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
],
)
##### GRPC
_GRPC_VERSION = "1.49.0" # https://github.com/grpc/grpc/releases/tag/v1.48.0
http_archive(
name = "com_github_grpc_grpc",
patch_args = ["-p1"],
patches = ["//grpc:build_grpc_with_cxx14.patch"],
sha256 = "15715e1847cc9e42014f02c727dbcb48e39dbdb90f79ad3d66fe4361709ff935",
strip_prefix = "grpc-" + _GRPC_VERSION,
urls = ["https://github.com/grpc/grpc/archive/refs/tags/v" + _GRPC_VERSION + ".tar.gz"],
)
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
grpc_deps()
load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
grpc_extra_deps()
# rules_go from https://github.com/bazelbuild/rules_go/releases/tag/v0.34.0
http_archive(
name = "aspect_rules_js",
sha256 = "76a04ef2120ee00231d85d1ff012ede23963733339ad8db81f590791a031f643",
strip_prefix = "rules_js-1.34.1",
url = "https://github.com/aspect-build/rules_js/releases/download/v1.34.1/rules_js-v1.34.1.tar.gz",
)
load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies")
rules_js_dependencies()
load("@aspect_rules_js//npm:npm_import.bzl", "pnpm_repository")
pnpm_repository(name = "pnpm")
http_archive(
name = "aspect_rules_ts",
sha256 = "4c3f34fff9f96ffc9c26635d8235a32a23a6797324486c7d23c1dfa477e8b451",
strip_prefix = "rules_ts-1.4.5",
url = "https://github.com/aspect-build/rules_ts/releases/download/v1.4.5/rules_ts-v1.4.5.tar.gz",
)
load("@aspect_rules_ts//ts:repositories.bzl", "rules_ts_dependencies")
rules_ts_dependencies(
# Since rules_ts doesn't always have the newest integrity hashes, we
# compute it manually here.
# $ curl --silent https://registry.npmjs.org/typescript/5.3.3 | jq ._integrity
ts_integrity = "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
ts_version_from = "//:package.json",
)
load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains")
nodejs_register_toolchains(
name = "nodejs",
node_version = DEFAULT_NODE_VERSION,
)
load("@com_github_google_flatbuffers//ts:repositories.bzl", "flatbuffers_npm")
flatbuffers_npm(
name = "flatbuffers_npm",
)
load("@flatbuffers_npm//:repositories.bzl", "npm_repositories")
npm_repositories()
http_archive(
name = "aspect_rules_esbuild",
sha256 = "098e38e5ee868c14a6484ba263b79e57d48afacfc361ba30137c757a9c4716d6",
strip_prefix = "rules_esbuild-0.15.0",
url = "https://github.com/aspect-build/rules_esbuild/releases/download/v0.15.0/rules_esbuild-v0.15.0.tar.gz",
)
# Register a toolchain containing esbuild npm package and native bindings
load("@aspect_rules_esbuild//esbuild:repositories.bzl", "LATEST_ESBUILD_VERSION", "esbuild_register_toolchains")
esbuild_register_toolchains(
name = "esbuild",
esbuild_version = LATEST_ESBUILD_VERSION,
)
http_archive(
name = "rules_bazel_integration_test",
sha256 = "3e24bc0fba88177cd0ae87c1e37bf7de5d5af8e812f00817a58498b1a8368fca",
urls = [
"https://github.com/bazel-contrib/rules_bazel_integration_test/releases/download/v0.31.0/rules_bazel_integration_test.v0.31.0.tar.gz",
],
)
load("@rules_bazel_integration_test//bazel_integration_test:deps.bzl", "bazel_integration_test_rules_dependencies")
bazel_integration_test_rules_dependencies()
load("@cgrindel_bazel_starlib//:deps.bzl", "bazel_starlib_dependencies")
bazel_starlib_dependencies()
load("@rules_bazel_integration_test//bazel_integration_test:defs.bzl", "bazel_binaries")
bazel_binaries(versions = ["6.3.2"])

View File

@@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -15,25 +15,27 @@
*/
#include <jni.h>
#include <string>
#include <search.h>
#include <string>
#include "generated/animal_generated.h"
using namespace com::fbs::app;
using namespace flatbuffers;
extern "C" JNIEXPORT jbyteArray JNICALL Java_com_flatbuffers_app_MainActivity_createAnimalFromJNI(
JNIEnv* env,
jobject /* this */) {
// create a new animal flatbuffers
auto fb = FlatBufferBuilder(1024);
auto tiger = CreateAnimalDirect(fb, "Tiger", "Roar", 300);
fb.Finish(tiger);
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_flatbuffers_app_MainActivity_createAnimalFromJNI(JNIEnv* env,
jobject /* this */) {
// create a new animal flatbuffers
auto fb = FlatBufferBuilder(1024);
auto tiger = CreateAnimalDirect(fb, "Tiger", "Roar", 300);
fb.Finish(tiger);
// copies it to a Java byte array.
auto buf = reinterpret_cast<jbyte*>(fb.GetBufferPointer());
int size = fb.GetSize();
auto ret = env->NewByteArray(size);
env->SetByteArrayRegion (ret, 0, fb.GetSize(), buf);
// copies it to a Java byte array.
auto buf = reinterpret_cast<jbyte*>(fb.GetBufferPointer());
int size = fb.GetSize();
auto ret = env->NewByteArray(size);
env->SetByteArrayRegion(ret, 0, fb.GetSize(), buf);
return ret;
}

View File

@@ -1,6 +1,5 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
#define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
@@ -9,9 +8,9 @@
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
FLATBUFFERS_VERSION_MINOR == 12 &&
FLATBUFFERS_VERSION_REVISION == 23,
"Non-compatible flatbuffers version included");
FLATBUFFERS_VERSION_MINOR == 12 &&
FLATBUFFERS_VERSION_REVISION == 23,
"Non-compatible flatbuffers version included");
namespace com {
namespace fbs {
@@ -27,29 +26,24 @@ struct Animal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
VT_SOUND = 6,
VT_WEIGHT = 8
};
const ::flatbuffers::String *name() const {
return GetPointer<const ::flatbuffers::String *>(VT_NAME);
const ::flatbuffers::String* name() const {
return GetPointer<const ::flatbuffers::String*>(VT_NAME);
}
const ::flatbuffers::String *sound() const {
return GetPointer<const ::flatbuffers::String *>(VT_SOUND);
const ::flatbuffers::String* sound() const {
return GetPointer<const ::flatbuffers::String*>(VT_SOUND);
}
uint16_t weight() const {
return GetField<uint16_t>(VT_WEIGHT, 0);
}
bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_SOUND) &&
uint16_t weight() const { return GetField<uint16_t>(VT_WEIGHT, 0); }
bool Verify(::flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) && VerifyOffset(verifier, VT_SOUND) &&
verifier.VerifyString(sound()) &&
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) &&
verifier.EndTable();
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) && verifier.EndTable();
}
};
struct AnimalBuilder {
typedef Animal Table;
::flatbuffers::FlatBufferBuilder &fbb_;
::flatbuffers::FlatBufferBuilder& fbb_;
::flatbuffers::uoffset_t start_;
void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
fbb_.AddOffset(Animal::VT_NAME, name);
@@ -60,8 +54,7 @@ struct AnimalBuilder {
void add_weight(uint16_t weight) {
fbb_.AddElement<uint16_t>(Animal::VT_WEIGHT, weight, 0);
}
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
::flatbuffers::Offset<Animal> Finish() {
@@ -72,7 +65,7 @@ struct AnimalBuilder {
};
inline ::flatbuffers::Offset<Animal> CreateAnimal(
::flatbuffers::FlatBufferBuilder &_fbb,
::flatbuffers::FlatBufferBuilder& _fbb,
::flatbuffers::Offset<::flatbuffers::String> name = 0,
::flatbuffers::Offset<::flatbuffers::String> sound = 0,
uint16_t weight = 0) {
@@ -84,45 +77,37 @@ inline ::flatbuffers::Offset<Animal> CreateAnimal(
}
inline ::flatbuffers::Offset<Animal> CreateAnimalDirect(
::flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
const char *sound = nullptr,
uint16_t weight = 0) {
::flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr,
const char* sound = nullptr, uint16_t weight = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto sound__ = sound ? _fbb.CreateString(sound) : 0;
return com::fbs::app::CreateAnimal(
_fbb,
name__,
sound__,
weight);
return com::fbs::app::CreateAnimal(_fbb, name__, sound__, weight);
}
inline const com::fbs::app::Animal *GetAnimal(const void *buf) {
inline const com::fbs::app::Animal* GetAnimal(const void* buf) {
return ::flatbuffers::GetRoot<com::fbs::app::Animal>(buf);
}
inline const com::fbs::app::Animal *GetSizePrefixedAnimal(const void *buf) {
inline const com::fbs::app::Animal* GetSizePrefixedAnimal(const void* buf) {
return ::flatbuffers::GetSizePrefixedRoot<com::fbs::app::Animal>(buf);
}
inline bool VerifyAnimalBuffer(
::flatbuffers::Verifier &verifier) {
inline bool VerifyAnimalBuffer(::flatbuffers::Verifier& verifier) {
return verifier.VerifyBuffer<com::fbs::app::Animal>(nullptr);
}
inline bool VerifySizePrefixedAnimalBuffer(
::flatbuffers::Verifier &verifier) {
inline bool VerifySizePrefixedAnimalBuffer(::flatbuffers::Verifier& verifier) {
return verifier.VerifySizePrefixedBuffer<com::fbs::app::Animal>(nullptr);
}
inline void FinishAnimalBuffer(
::flatbuffers::FlatBufferBuilder &fbb,
::flatbuffers::FlatBufferBuilder& fbb,
::flatbuffers::Offset<com::fbs::app::Animal> root) {
fbb.Finish(root);
}
inline void FinishSizePrefixedAnimalBuffer(
::flatbuffers::FlatBufferBuilder &fbb,
::flatbuffers::FlatBufferBuilder& fbb,
::flatbuffers::Offset<com::fbs::app::Animal> root) {
fbb.FinishSizePrefixed(root);
}

View File

@@ -1,9 +1,9 @@
package com.flatbuffers.app
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.fbs.app.Animal
import com.google.flatbuffers.FlatBufferBuilder
import java.nio.ByteBuffer
@@ -27,14 +27,15 @@ class MainActivity : AppCompatActivity() {
private external fun createAnimalFromJNI(): ByteArray
// Create a "Cow" Animal flatbuffers from Kotlin
private fun createAnimalFromKotlin():Animal {
private fun createAnimalFromKotlin(): Animal {
val fb = FlatBufferBuilder(100)
val cowOffset = Animal.createAnimal(
builder = fb,
nameOffset = fb.createString("Cow"),
soundOffset = fb.createString("Moo"),
weight = 720u
)
val cowOffset =
Animal.createAnimal(
builder = fb,
nameOffset = fb.createString("Cow"),
soundOffset = fb.createString("Moo"),
weight = 720u,
)
fb.finish(cowOffset)
return Animal.getRootAsAnimal(fb.dataBuffer())
}

View File

@@ -2,83 +2,101 @@
package com.fbs.app
import com.google.flatbuffers.BaseVector
import com.google.flatbuffers.BooleanVector
import com.google.flatbuffers.ByteVector
import com.google.flatbuffers.Constants
import com.google.flatbuffers.DoubleVector
import com.google.flatbuffers.FlatBufferBuilder
import com.google.flatbuffers.FloatVector
import com.google.flatbuffers.LongVector
import com.google.flatbuffers.StringVector
import com.google.flatbuffers.Struct
import com.google.flatbuffers.Table
import com.google.flatbuffers.UnionVector
import java.nio.ByteBuffer
import java.nio.ByteOrder
import kotlin.math.sign
@Suppress("unused")
@kotlin.ExperimentalUnsignedTypes
class Animal : Table() {
fun __init(_i: Int, _bb: ByteBuffer) {
__reset(_i, _bb)
fun __init(_i: Int, _bb: ByteBuffer) {
__reset(_i, _bb)
}
fun __assign(_i: Int, _bb: ByteBuffer): Animal {
__init(_i, _bb)
return this
}
val name: String?
get() {
val o = __offset(4)
return if (o != 0) {
__string(o + bb_pos)
} else {
null
}
}
fun __assign(_i: Int, _bb: ByteBuffer) : Animal {
__init(_i, _bb)
return this
val nameAsByteBuffer: ByteBuffer
get() = __vector_as_bytebuffer(4, 1)
fun nameInByteBuffer(_bb: ByteBuffer): ByteBuffer = __vector_in_bytebuffer(_bb, 4, 1)
val sound: String?
get() {
val o = __offset(6)
return if (o != 0) {
__string(o + bb_pos)
} else {
null
}
}
val name : String?
get() {
val o = __offset(4)
return if (o != 0) {
__string(o + bb_pos)
} else {
null
}
}
val nameAsByteBuffer : ByteBuffer get() = __vector_as_bytebuffer(4, 1)
fun nameInByteBuffer(_bb: ByteBuffer) : ByteBuffer = __vector_in_bytebuffer(_bb, 4, 1)
val sound : String?
get() {
val o = __offset(6)
return if (o != 0) {
__string(o + bb_pos)
} else {
null
}
}
val soundAsByteBuffer : ByteBuffer get() = __vector_as_bytebuffer(6, 1)
fun soundInByteBuffer(_bb: ByteBuffer) : ByteBuffer = __vector_in_bytebuffer(_bb, 6, 1)
val weight : UShort
get() {
val o = __offset(8)
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
}
companion object {
fun validateVersion() = Constants.FLATBUFFERS_25_1_21()
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
_bb.order(ByteOrder.LITTLE_ENDIAN)
return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb))
}
fun createAnimal(builder: FlatBufferBuilder, nameOffset: Int, soundOffset: Int, weight: UShort) : Int {
builder.startTable(3)
addSound(builder, soundOffset)
addName(builder, nameOffset)
addWeight(builder, weight)
return endAnimal(builder)
}
fun startAnimal(builder: FlatBufferBuilder) = builder.startTable(3)
fun addName(builder: FlatBufferBuilder, name: Int) = builder.addOffset(0, name, 0)
fun addSound(builder: FlatBufferBuilder, sound: Int) = builder.addOffset(1, sound, 0)
fun addWeight(builder: FlatBufferBuilder, weight: UShort) = builder.addShort(2, weight.toShort(), 0)
fun endAnimal(builder: FlatBufferBuilder) : Int {
val o = builder.endTable()
return o
}
fun finishAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finish(offset)
fun finishSizePrefixedAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finishSizePrefixed(offset)
val soundAsByteBuffer: ByteBuffer
get() = __vector_as_bytebuffer(6, 1)
fun soundInByteBuffer(_bb: ByteBuffer): ByteBuffer = __vector_in_bytebuffer(_bb, 6, 1)
val weight: UShort
get() {
val o = __offset(8)
return if (o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
}
companion object {
fun validateVersion() = Constants.FLATBUFFERS_25_12_19()
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
_bb.order(ByteOrder.LITTLE_ENDIAN)
return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb))
}
fun createAnimal(
builder: FlatBufferBuilder,
nameOffset: Int,
soundOffset: Int,
weight: UShort,
): Int {
builder.startTable(3)
addSound(builder, soundOffset)
addName(builder, nameOffset)
addWeight(builder, weight)
return endAnimal(builder)
}
fun startAnimal(builder: FlatBufferBuilder) = builder.startTable(3)
fun addName(builder: FlatBufferBuilder, name: Int) = builder.addOffset(0, name, 0)
fun addSound(builder: FlatBufferBuilder, sound: Int) = builder.addOffset(1, sound, 0)
fun addWeight(builder: FlatBufferBuilder, weight: UShort) =
builder.addShort(2, weight.toShort(), 0)
fun endAnimal(builder: FlatBufferBuilder): Int {
val o = builder.endTable()
return o
}
fun finishAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finish(offset)
fun finishSizePrefixedAnimalBuffer(builder: FlatBufferBuilder, offset: Int) =
builder.finishSizePrefixed(offset)
}
}

View File

@@ -8,12 +8,12 @@ struct Bench {
inline void Add(int64_t value) { sum += value; }
virtual uint8_t *Encode(void *buf, int64_t &len) = 0;
virtual void *Decode(void *buf, int64_t len) = 0;
virtual int64_t Use(void *decoded) = 0;
virtual void Dealloc(void *decoded) = 0;
virtual uint8_t* Encode(void* buf, int64_t& len) = 0;
virtual void* Decode(void* buf, int64_t len) = 0;
virtual int64_t Use(void* decoded) = 0;
virtual void Dealloc(void* decoded) = 0;
int64_t sum = 0;
};
#endif // BENCHMARKS_CPP_BENCH_H_
#endif // BENCHMARKS_CPP_BENCH_H_

View File

@@ -5,8 +5,8 @@
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
#include "benchmarks/cpp/raw/raw_bench.h"
static inline void Encode(benchmark::State &state,
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
static inline void Encode(benchmark::State& state,
std::unique_ptr<Bench>& bench, uint8_t* buffer) {
int64_t length;
for (auto _ : state) {
bench->Encode(buffer, length);
@@ -14,31 +14,33 @@ static inline void Encode(benchmark::State &state,
}
}
static inline void Decode(benchmark::State &state,
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
static inline void Decode(benchmark::State& state,
std::unique_ptr<Bench>& bench, uint8_t* buffer) {
int64_t length;
uint8_t *encoded = bench->Encode(buffer, length);
uint8_t* encoded = bench->Encode(buffer, length);
for (auto _ : state) {
void *decoded = bench->Decode(encoded, length);
void* decoded = bench->Decode(encoded, length);
benchmark::DoNotOptimize(decoded);
}
}
static inline void Use(benchmark::State &state, std::unique_ptr<Bench> &bench,
uint8_t *buffer, int64_t check_sum) {
static inline void Use(benchmark::State& state, std::unique_ptr<Bench>& bench,
uint8_t* buffer, int64_t check_sum) {
int64_t length;
uint8_t *encoded = bench->Encode(buffer, length);
void *decoded = bench->Decode(encoded, length);
uint8_t* encoded = bench->Encode(buffer, length);
void* decoded = bench->Decode(encoded, length);
int64_t sum = 0;
for (auto _ : state) { sum = bench->Use(decoded); }
for (auto _ : state) {
sum = bench->Use(decoded);
}
EXPECT_EQ(sum, check_sum);
}
static void BM_Flatbuffers_Encode(benchmark::State &state) {
static void BM_Flatbuffers_Encode(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];
@@ -48,7 +50,7 @@ static void BM_Flatbuffers_Encode(benchmark::State &state) {
}
BENCHMARK(BM_Flatbuffers_Encode);
static void BM_Flatbuffers_Decode(benchmark::State &state) {
static void BM_Flatbuffers_Decode(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];
@@ -58,7 +60,7 @@ static void BM_Flatbuffers_Decode(benchmark::State &state) {
}
BENCHMARK(BM_Flatbuffers_Decode);
static void BM_Flatbuffers_Use(benchmark::State &state) {
static void BM_Flatbuffers_Use(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];
@@ -68,7 +70,7 @@ static void BM_Flatbuffers_Use(benchmark::State &state) {
}
BENCHMARK(BM_Flatbuffers_Use);
static void BM_Raw_Encode(benchmark::State &state) {
static void BM_Raw_Encode(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];
@@ -77,7 +79,7 @@ static void BM_Raw_Encode(benchmark::State &state) {
}
BENCHMARK(BM_Raw_Encode);
static void BM_Raw_Decode(benchmark::State &state) {
static void BM_Raw_Decode(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];
@@ -86,7 +88,7 @@ static void BM_Raw_Decode(benchmark::State &state) {
}
BENCHMARK(BM_Raw_Decode);
static void BM_Raw_Use(benchmark::State &state) {
static void BM_Raw_Use(benchmark::State& state) {
const int64_t kBufferLength = 1024;
uint8_t buffer[kBufferLength];

View File

@@ -1,6 +1,5 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
@@ -9,9 +8,9 @@
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 24 &&
FLATBUFFERS_VERSION_MINOR == 12 &&
FLATBUFFERS_VERSION_REVISION == 23,
"Non-compatible flatbuffers version included");
FLATBUFFERS_VERSION_MINOR == 12 &&
FLATBUFFERS_VERSION_REVISION == 23,
"Non-compatible flatbuffers version included");
namespace benchmarks_flatbuffers {
@@ -34,25 +33,16 @@ enum Enum : int16_t {
};
inline const Enum (&EnumValuesEnum())[3] {
static const Enum values[] = {
Enum_Apples,
Enum_Pears,
Enum_Bananas
};
static const Enum values[] = {Enum_Apples, Enum_Pears, Enum_Bananas};
return values;
}
inline const char * const *EnumNamesEnum() {
static const char * const names[4] = {
"Apples",
"Pears",
"Bananas",
nullptr
};
inline const char* const* EnumNamesEnum() {
static const char* const names[4] = {"Apples", "Pears", "Bananas", nullptr};
return names;
}
inline const char *EnumNameEnum(Enum e) {
inline const char* EnumNameEnum(Enum e) {
if (flatbuffers::IsOutRange(e, Enum_Apples, Enum_Bananas)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesEnum()[index];
@@ -67,12 +57,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
uint32_t length_;
public:
Foo()
: id_(0),
count_(0),
prefix_(0),
padding0__(0),
length_(0) {
Foo() : id_(0), count_(0), prefix_(0), padding0__(0), length_(0) {
(void)padding0__;
}
Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length)
@@ -83,18 +68,10 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
length_(flatbuffers::EndianScalar(_length)) {
(void)padding0__;
}
uint64_t id() const {
return flatbuffers::EndianScalar(id_);
}
int16_t count() const {
return flatbuffers::EndianScalar(count_);
}
int8_t prefix() const {
return flatbuffers::EndianScalar(prefix_);
}
uint32_t length() const {
return flatbuffers::EndianScalar(length_);
}
uint64_t id() const { return flatbuffers::EndianScalar(id_); }
int16_t count() const { return flatbuffers::EndianScalar(count_); }
int8_t prefix() const { return flatbuffers::EndianScalar(prefix_); }
uint32_t length() const { return flatbuffers::EndianScalar(length_); }
};
FLATBUFFERS_STRUCT_END(Foo, 16);
@@ -104,20 +81,17 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
int32_t time_;
float ratio_;
uint16_t size_;
int16_t padding0__; int32_t padding1__;
int16_t padding0__;
int32_t padding1__;
public:
Bar()
: parent_(),
time_(0),
ratio_(0),
size_(0),
padding0__(0),
padding1__(0) {
: parent_(), time_(0), ratio_(0), size_(0), padding0__(0), padding1__(0) {
(void)padding0__;
(void)padding1__;
}
Bar(const benchmarks_flatbuffers::Foo &_parent, int32_t _time, float _ratio, uint16_t _size)
Bar(const benchmarks_flatbuffers::Foo& _parent, int32_t _time, float _ratio,
uint16_t _size)
: parent_(_parent),
time_(flatbuffers::EndianScalar(_time)),
ratio_(flatbuffers::EndianScalar(_ratio)),
@@ -127,18 +101,10 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
(void)padding0__;
(void)padding1__;
}
const benchmarks_flatbuffers::Foo &parent() const {
return parent_;
}
int32_t time() const {
return flatbuffers::EndianScalar(time_);
}
float ratio() const {
return flatbuffers::EndianScalar(ratio_);
}
uint16_t size() const {
return flatbuffers::EndianScalar(size_);
}
const benchmarks_flatbuffers::Foo& parent() const { return parent_; }
int32_t time() const { return flatbuffers::EndianScalar(time_); }
float ratio() const { return flatbuffers::EndianScalar(ratio_); }
uint16_t size() const { return flatbuffers::EndianScalar(size_); }
};
FLATBUFFERS_STRUCT_END(Bar, 32);
@@ -150,34 +116,28 @@ struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_RATING = 8,
VT_POSTFIX = 10
};
const benchmarks_flatbuffers::Bar *sibling() const {
return GetStruct<const benchmarks_flatbuffers::Bar *>(VT_SIBLING);
const benchmarks_flatbuffers::Bar* sibling() const {
return GetStruct<const benchmarks_flatbuffers::Bar*>(VT_SIBLING);
}
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(VT_NAME);
}
double rating() const {
return GetField<double>(VT_RATING, 0.0);
}
uint8_t postfix() const {
return GetField<uint8_t>(VT_POSTFIX, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
double rating() const { return GetField<double>(VT_RATING, 0.0); }
uint8_t postfix() const { return GetField<uint8_t>(VT_POSTFIX, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<benchmarks_flatbuffers::Bar>(verifier, VT_SIBLING, 8) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_NAME) && verifier.VerifyString(name()) &&
VerifyField<double>(verifier, VT_RATING, 8) &&
VerifyField<uint8_t>(verifier, VT_POSTFIX, 1) &&
verifier.EndTable();
VerifyField<uint8_t>(verifier, VT_POSTFIX, 1) && verifier.EndTable();
}
};
struct FooBarBuilder {
typedef FooBar Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_sibling(const benchmarks_flatbuffers::Bar *sibling) {
void add_sibling(const benchmarks_flatbuffers::Bar* sibling) {
fbb_.AddStruct(FooBar::VT_SIBLING, sibling);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
@@ -189,8 +149,7 @@ struct FooBarBuilder {
void add_postfix(uint8_t postfix) {
fbb_.AddElement<uint8_t>(FooBar::VT_POSTFIX, postfix, 0);
}
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<FooBar> Finish() {
@@ -201,10 +160,9 @@ struct FooBarBuilder {
};
inline flatbuffers::Offset<FooBar> CreateFooBar(
flatbuffers::FlatBufferBuilder &_fbb,
const benchmarks_flatbuffers::Bar *sibling = nullptr,
flatbuffers::Offset<flatbuffers::String> name = 0,
double rating = 0.0,
flatbuffers::FlatBufferBuilder& _fbb,
const benchmarks_flatbuffers::Bar* sibling = nullptr,
flatbuffers::Offset<flatbuffers::String> name = 0, double rating = 0.0,
uint8_t postfix = 0) {
FooBarBuilder builder_(_fbb);
builder_.add_rating(rating);
@@ -215,18 +173,12 @@ inline flatbuffers::Offset<FooBar> CreateFooBar(
}
inline flatbuffers::Offset<FooBar> CreateFooBarDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const benchmarks_flatbuffers::Bar *sibling = nullptr,
const char *name = nullptr,
double rating = 0.0,
uint8_t postfix = 0) {
flatbuffers::FlatBufferBuilder& _fbb,
const benchmarks_flatbuffers::Bar* sibling = nullptr,
const char* name = nullptr, double rating = 0.0, uint8_t postfix = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0;
return benchmarks_flatbuffers::CreateFooBar(
_fbb,
sibling,
name__,
rating,
postfix);
return benchmarks_flatbuffers::CreateFooBar(_fbb, sibling, name__, rating,
postfix);
}
struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -237,49 +189,53 @@ struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FRUIT = 8,
VT_LOCATION = 10
};
const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *>(VT_LIST);
}
bool initialized() const {
return GetField<uint8_t>(VT_INITIALIZED, 0) != 0;
const flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*
list() const {
return GetPointer<const flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*>(VT_LIST);
}
bool initialized() const { return GetField<uint8_t>(VT_INITIALIZED, 0) != 0; }
benchmarks_flatbuffers::Enum fruit() const {
return static_cast<benchmarks_flatbuffers::Enum>(GetField<int16_t>(VT_FRUIT, 0));
return static_cast<benchmarks_flatbuffers::Enum>(
GetField<int16_t>(VT_FRUIT, 0));
}
const flatbuffers::String *location() const {
return GetPointer<const flatbuffers::String *>(VT_LOCATION);
const flatbuffers::String* location() const {
return GetPointer<const flatbuffers::String*>(VT_LOCATION);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_LIST) &&
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_LIST) &&
verifier.VerifyVector(list()) &&
verifier.VerifyVectorOfTables(list()) &&
VerifyField<uint8_t>(verifier, VT_INITIALIZED, 1) &&
VerifyField<int16_t>(verifier, VT_FRUIT, 2) &&
VerifyOffset(verifier, VT_LOCATION) &&
verifier.VerifyString(location()) &&
verifier.EndTable();
verifier.VerifyString(location()) && verifier.EndTable();
}
};
struct FooBarContainerBuilder {
typedef FooBarContainer Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_list(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list) {
void add_list(flatbuffers::Offset<flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>>
list) {
fbb_.AddOffset(FooBarContainer::VT_LIST, list);
}
void add_initialized(bool initialized) {
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED, static_cast<uint8_t>(initialized), 0);
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED,
static_cast<uint8_t>(initialized), 0);
}
void add_fruit(benchmarks_flatbuffers::Enum fruit) {
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT, static_cast<int16_t>(fruit), 0);
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT,
static_cast<int16_t>(fruit), 0);
}
void add_location(flatbuffers::Offset<flatbuffers::String> location) {
fbb_.AddOffset(FooBarContainer::VT_LOCATION, location);
}
explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<FooBarContainer> Finish() {
@@ -290,8 +246,10 @@ struct FooBarContainerBuilder {
};
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list = 0,
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>>
list = 0,
bool initialized = false,
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
flatbuffers::Offset<flatbuffers::String> location = 0) {
@@ -304,47 +262,52 @@ inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
}
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainerDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list = nullptr,
flatbuffers::FlatBufferBuilder& _fbb,
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*
list = nullptr,
bool initialized = false,
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
const char *location = nullptr) {
auto list__ = list ? _fbb.CreateVector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list) : 0;
const char* location = nullptr) {
auto list__ =
list ? _fbb.CreateVector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list)
: 0;
auto location__ = location ? _fbb.CreateString(location) : 0;
return benchmarks_flatbuffers::CreateFooBarContainer(
_fbb,
list__,
initialized,
fruit,
location__);
_fbb, list__, initialized, fruit, location__);
}
inline const benchmarks_flatbuffers::FooBarContainer *GetFooBarContainer(const void *buf) {
inline const benchmarks_flatbuffers::FooBarContainer* GetFooBarContainer(
const void* buf) {
return flatbuffers::GetRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
}
inline const benchmarks_flatbuffers::FooBarContainer *GetSizePrefixedFooBarContainer(const void *buf) {
return flatbuffers::GetSizePrefixedRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
inline const benchmarks_flatbuffers::FooBarContainer*
GetSizePrefixedFooBarContainer(const void* buf) {
return flatbuffers::GetSizePrefixedRoot<
benchmarks_flatbuffers::FooBarContainer>(buf);
}
inline bool VerifyFooBarContainerBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
inline bool VerifyFooBarContainerBuffer(flatbuffers::Verifier& verifier) {
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(
nullptr);
}
inline bool VerifySizePrefixedFooBarContainerBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
flatbuffers::Verifier& verifier) {
return verifier
.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(
nullptr);
}
inline void FinishFooBarContainerBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::FlatBufferBuilder& fbb,
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
fbb.Finish(root);
}
inline void FinishSizePrefixedFooBarContainerBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::FlatBufferBuilder& fbb,
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
fbb.FinishSizePrefixed(root);
}

View File

@@ -13,10 +13,10 @@ using namespace benchmarks_flatbuffers;
namespace {
struct FlatBufferBench : Bench {
explicit FlatBufferBench(int64_t initial_size, Allocator *allocator)
explicit FlatBufferBench(int64_t initial_size, Allocator* allocator)
: fbb(initial_size, allocator, false) {}
uint8_t *Encode(void *, int64_t &len) override {
uint8_t* Encode(void*, int64_t& len) override {
fbb.Clear();
const int kVectorLength = 3;
@@ -40,7 +40,7 @@ struct FlatBufferBench : Bench {
return fbb.GetBufferPointer();
}
int64_t Use(void *decoded) override {
int64_t Use(void* decoded) override {
sum = 0;
auto foobarcontainer = GetFooBarContainer(decoded);
sum = 0;
@@ -56,7 +56,7 @@ struct FlatBufferBench : Bench {
Add(static_cast<int64_t>(bar->ratio()));
Add(bar->size());
Add(bar->time());
auto &foo = bar->parent();
auto& foo = bar->parent();
Add(foo.count());
Add(foo.id());
Add(foo.length());
@@ -65,8 +65,8 @@ struct FlatBufferBench : Bench {
return sum;
}
void *Decode(void *buffer, int64_t) override { return buffer; }
void Dealloc(void *) override {};
void* Decode(void* buffer, int64_t) override { return buffer; }
void Dealloc(void*) override {};
FlatBufferBuilder fbb;
};
@@ -74,7 +74,7 @@ struct FlatBufferBench : Bench {
} // namespace
std::unique_ptr<Bench> NewFlatBuffersBench(int64_t initial_size,
Allocator *allocator) {
Allocator* allocator) {
return std::unique_ptr<FlatBufferBench>(
new FlatBufferBench(initial_size, allocator));
}

View File

@@ -8,16 +8,16 @@
#include "include/flatbuffers/flatbuffers.h"
struct StaticAllocator : public flatbuffers::Allocator {
explicit StaticAllocator(uint8_t *buffer) : buffer_(buffer) {}
explicit StaticAllocator(uint8_t* buffer) : buffer_(buffer) {}
uint8_t *allocate(size_t) override { return buffer_; }
uint8_t* allocate(size_t) override { return buffer_; }
void deallocate(uint8_t *, size_t) override {}
void deallocate(uint8_t*, size_t) override {}
uint8_t *buffer_;
uint8_t* buffer_;
};
std::unique_ptr<Bench> NewFlatBuffersBench(
int64_t initial_size = 1024, flatbuffers::Allocator *allocator = nullptr);
int64_t initial_size = 1024, flatbuffers::Allocator* allocator = nullptr);
#endif // BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_

View File

@@ -45,8 +45,8 @@ struct FooBarContainer {
};
struct RawBench : Bench {
uint8_t *Encode(void *buf, int64_t &len) override {
FooBarContainer *fbc = new (buf) FooBarContainer;
uint8_t* Encode(void* buf, int64_t& len) override {
FooBarContainer* fbc = new (buf) FooBarContainer;
strcpy(fbc->location, "http://google.com/flatbuffers/"); // Unsafe eek!
fbc->location_len = (int)strlen(fbc->location);
fbc->fruit = Bananas;
@@ -54,16 +54,16 @@ struct RawBench : Bench {
for (int i = 0; i < kVectorLength; i++) {
// We add + i to not make these identical copies for a more realistic
// compression test.
auto &foobar = fbc->list[i];
auto& foobar = fbc->list[i];
foobar.rating = 3.1415432432445543543 + i;
foobar.postfix = '!' + i;
strcpy(foobar.name, "Hello, World!");
foobar.name_len = (int)strlen(foobar.name);
auto &bar = foobar.sibling;
auto& bar = foobar.sibling;
bar.ratio = 3.14159f + i;
bar.size = 10000 + i;
bar.time = 123456 + i;
auto &foo = bar.parent;
auto& foo = bar.parent;
foo.id = 0xABADCAFEABADCAFE + i;
foo.count = 10000 + i;
foo.length = 1000000 + i;
@@ -71,11 +71,11 @@ struct RawBench : Bench {
}
len = sizeof(FooBarContainer);
return reinterpret_cast<uint8_t *>(fbc);
return reinterpret_cast<uint8_t*>(fbc);
};
int64_t Use(void *decoded) override {
auto foobarcontainer = reinterpret_cast<FooBarContainer *>(decoded);
int64_t Use(void* decoded) override {
auto foobarcontainer = reinterpret_cast<FooBarContainer*>(decoded);
sum = 0;
Add(foobarcontainer->initialized);
Add(foobarcontainer->location_len);
@@ -89,7 +89,7 @@ struct RawBench : Bench {
Add(static_cast<int64_t>(bar->ratio));
Add(bar->size);
Add(bar->time);
auto &foo = bar->parent;
auto& foo = bar->parent;
Add(foo.count);
Add(foo.id);
Add(foo.length);
@@ -98,8 +98,8 @@ struct RawBench : Bench {
return sum;
}
void *Decode(void *buf, int64_t) override { return buf; }
void Dealloc(void *) override{};
void* Decode(void* buf, int64_t) override { return buf; }
void Dealloc(void*) override {};
};
} // namespace

View File

@@ -15,8 +15,8 @@
*/
import Benchmark
import CoreFoundation
import FlatBuffers
import Foundation
@usableFromInline
struct AA: NativeStruct {
@@ -29,6 +29,15 @@ struct AA: NativeStruct {
}
let benchmarks = {
let oneGB: Int32 = 1_024_000_000
let data = {
var array = [8888.88, 8888.88]
var data = Data()
array.withUnsafeBytes { ptr in
data.append(contentsOf: ptr)
}
return data
}()
let ints: [Int] = Array(repeating: 42, count: 100)
let bytes: [UInt8] = Array(repeating: 42, count: 100)
let str10 = (0...9).map { _ -> String in "x" }.joined()
@@ -73,12 +82,25 @@ let benchmarks = {
Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in
for _ in benchmark.scaledIterations {
blackHole(FlatBufferBuilder(initialSize: 1_024_000_000))
blackHole(FlatBufferBuilder(initialSize: oneGB))
}
}
Benchmark(
"Allocating ByteBuffer 1GB",
configuration: singleConfiguration)
{ benchmark in
let memory = UnsafeMutableRawPointer.allocate(
byteCount: 1_024_000_000,
alignment: 1)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
}
}
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
var fb = FlatBufferBuilder(initialSize: 1_024_000_000)
var fb = FlatBufferBuilder(initialSize: oneGB)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.clear())
@@ -86,7 +108,7 @@ let benchmarks = {
}
Benchmark("Strings 10") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10))
@@ -94,7 +116,7 @@ let benchmarks = {
}
Benchmark("Strings 100") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100))
@@ -102,7 +124,7 @@ let benchmarks = {
}
Benchmark("Vector 1 Bytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
@@ -110,7 +132,7 @@ let benchmarks = {
}
Benchmark("Vector 1 Ints") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
@@ -118,7 +140,7 @@ let benchmarks = {
}
Benchmark("Vector 100 Ints") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
@@ -126,7 +148,7 @@ let benchmarks = {
}
Benchmark("Vector 100 Bytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes))
@@ -134,7 +156,7 @@ let benchmarks = {
}
Benchmark("Vector 100 ContiguousBytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20)
var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement()
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
@@ -158,6 +180,26 @@ let benchmarks = {
}
}
Benchmark(
"FlatBufferBuilder Start table",
configuration: kiloConfiguration)
{ benchmark in
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let s = fb.startTable(with: 4)
blackHole(fb.endTable(at: s))
}
}
Benchmark("Struct") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(fb.create(struct: array.first!))
}
}
Benchmark("Structs") { benchmark in
let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024
var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))
@@ -176,7 +218,7 @@ let benchmarks = {
let start = fb.startTable(with: 1)
fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start))
fb.finish(offset: root)
blackHole(fb.finish(offset: root))
}
Benchmark("Vector of Offsets") { benchmark in
@@ -198,4 +240,11 @@ let benchmarks = {
blackHole(fb.endTable(at: s))
}
}
Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data)
for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0))
}
}
}

View File

@@ -1,4 +1,4 @@
// swift-tools-version:5.8
// swift-tools-version:5.10
/*
* Copyright 2020 Google Inc. All rights reserved.
*

View File

@@ -6,4 +6,4 @@ To open the benchmarks in xcode use:
or running them directly within terminal using:
`swift package benchmark`
`swift package benchmark`

View File

@@ -7,19 +7,13 @@ Rules for building C++ flatbuffers with Bazel.
load("@rules_cc//cc:defs.bzl", "cc_library")
def repo_name(label):
if hasattr(label, "repo_name"): # Added in Bazel 7.1
return label.repo_name
else:
return "com_github_google_flatbuffers"
TRUE_FLATC_PATH = Label("//:flatc")
DEFAULT_INCLUDE_PATHS = [
"./",
"$(GENDIR)",
"$(BINDIR)",
"$(execpath %s).runfiles/%s" % (TRUE_FLATC_PATH, repo_name(TRUE_FLATC_PATH)),
"$(execpath %s).runfiles/%s" % (TRUE_FLATC_PATH, TRUE_FLATC_PATH.repo_name),
]
def default_include_paths(flatc_path):
@@ -27,7 +21,7 @@ def default_include_paths(flatc_path):
"./",
"$(GENDIR)",
"$(BINDIR)",
"$(execpath %s).runfiles/%s" % (flatc_path, repo_name(flatc_path)),
"$(execpath %s).runfiles/%s" % (flatc_path, flatc_path.repo_name),
]
DEFAULT_FLATC_ARGS = [
@@ -142,6 +136,8 @@ def flatbuffer_library_public(
reflection_genrule_cmd = " ".join([
"SRCS=($(SRCS));",
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
# Move the .fbs file into the current package if it is not there already
'if [[ $$(dirname $$f) != "{0}" ]]; then s="$$f"; f="{0}/$$(basename "$$f")"; mkdir -p "{0}"; mv "$$s" "$$f"; fi;'.format(native.package_relative_label(":invalid").package),
"$(location %s)" % (TRUE_FLATC_PATH),
"-b --schema",
" ".join(flatc_args),
@@ -152,9 +148,10 @@ def flatbuffer_library_public(
"done",
])
reflection_outs = [
(out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
(out_prefix + "%s.bfbs") % (native.package_relative_label(s).name.removesuffix(".fbs"))
for s in srcs
]
native.genrule(
name = "%s_srcs" % reflection_name,
srcs = srcs + includes,
@@ -190,6 +187,7 @@ def flatbuffer_cc_library(
visibility = None,
compatible_with = None,
restricted_to = None,
filename_suffix = "_generated",
target_compatible_with = None,
srcs_filegroup_visibility = None,
gen_reflections = False):
@@ -233,10 +231,13 @@ def flatbuffer_cc_library(
Fileset([name]_reflection): (Optional) all generated reflection binaries.
cc_library([name]): library with sources and flatbuffers deps.
"""
output_headers = [
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1].split(":")[-1])
for s in srcs
]
output_headers = []
for s in srcs:
base_name = s.split("/")[-1].split(":")[-1].replace(".fbs", "")
header = out_prefix + base_name + filename_suffix + ".h"
output_headers.append(header)
if deps and includes:
# There is no inherent reason we couldn't support both, but this discourages
# use of includes without good reason.

View File

@@ -1,12 +0,0 @@
cmake_minimum_required(VERSION 2.8)
message(STATUS "Conan FlatBuffers Wrapper")
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
if (WIN32 AND MSVC_LIKE AND FLATBUFFERS_BUILD_SHAREDLIB)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif(WIN32 AND MSVC_LIKE AND FLATBUFFERS_BUILD_SHAREDLIB)
include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt)

View File

@@ -1,50 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
import subprocess
from cpt.packager import ConanMultiPackager
def get_branch():
try:
for line in subprocess.check_output("git branch", shell=True).decode().splitlines():
line = line.strip()
if line.startswith("*") and " (HEAD detached" not in line:
return line.replace("*", "", 1).strip()
return ""
except Exception:
pass
return ""
def get_version():
version = get_branch()
match = re.search(r"v(\d+\.\d+\.\d+.*)", version)
if match:
return match.group(1)
return version
def get_reference(username):
return "flatbuffers/{}@google/stable".format(get_version())
if __name__ == "__main__":
login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel")
username = os.getenv("CONAN_USERNAME", "google")
upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers")
stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*")
test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package"))
upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
builder = ConanMultiPackager(reference=get_reference(username),
username=username,
login_username=login_username,
upload=upload,
stable_branch_pattern=stable_branch_pattern,
upload_only_when_stable=upload_only_when_stable,
test_folder=test_folder)
builder.add_common_builds(pure_c=False)
builder.run()

View File

@@ -1,9 +0,0 @@
project(test_package CXX)
cmake_minimum_required(VERSION 2.8.11)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)

View File

@@ -1,21 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from conans import ConanFile, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
self.run("flatc --version", run_environment=True)
self.run("flathash fnv1_16 conan", run_environment=True)

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Conan recipe package for Google FlatBuffers
"""
import os
import shutil
from conans import ConanFile, CMake, tools
class FlatbuffersConan(ConanFile):
name = "flatbuffers"
license = "Apache-2.0"
url = "https://github.com/google/flatbuffers"
homepage = "http://google.github.io/flatbuffers/"
author = "Wouter van Oortmerssen"
topics = ("conan", "flatbuffers", "serialization", "rpc", "json-parser")
description = "Memory Efficient Serialization Library"
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
generators = "cmake"
exports = "LICENSE"
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"]
def source(self):
"""Wrap the original CMake file to call conan_basic_setup
"""
shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt")
shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
def config_options(self):
"""Remove fPIC option on Windows platform
"""
if self.settings.os == "Windows":
self.options.remove("fPIC")
def configure_cmake(self):
"""Create CMake instance and execute configure step
"""
cmake = CMake(self)
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared
cmake.configure()
return cmake
def build(self):
"""Configure, build and install FlatBuffers using CMake.
"""
cmake = self.configure_cmake()
cmake.build()
def package(self):
"""Copy Flatbuffers' artifacts to package folder
"""
cmake = self.configure_cmake()
cmake.install()
self.copy(pattern="LICENSE", dst="licenses")
self.copy(pattern="FindFlatBuffers.cmake", dst=os.path.join("lib", "cmake", "flatbuffers"), src="CMake")
self.copy(pattern="flathash*", dst="bin", src="bin")
self.copy(pattern="flatc*", dst="bin", src="bin")
if self.settings.os == "Windows" and self.options.shared:
if self.settings.compiler == "Visual Studio":
shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "%s.dll" % self.name))
elif self.settings.compiler == "gcc":
shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name))
def package_info(self):
"""Collect built libraries names and solve flatc path.
"""
self.cpp_info.libs = tools.collect_libs(self)
self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")

View File

@@ -1,5 +1,11 @@
# Changelog
## 25.9.23
- use enhanced enums (#8313)
- fix incorrect write in Float64 write method (#8290)
- code format improvements (#8707)
## 23.5.26
- omit type annotationes for local variables (#7067, #7069, #7070)

View File

@@ -15,6 +15,7 @@
*/
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_my_game.sample_generated.dart' as my_game;
// Example how to use FlatBuffers to create and read binary buffers.
@@ -78,7 +79,8 @@ void builderTest() {
builder.finish(monsteroff);
if (verify(builder.buffer)) {
print(
"The FlatBuffer was successfully created with a builder and verified!");
"The FlatBuffer was successfully created with a builder and verified!",
);
}
}
@@ -94,7 +96,10 @@ void objectBuilderTest() {
name: 'Orc',
inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
color: my_game.Color.Red,
weapons: [my_game.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
weapons: [
my_game.WeaponObjectBuilder(name: 'Sword', damage: 3),
axe,
],
equippedType: my_game.EquipmentTypeId.Weapon,
equipped: axe,
);
@@ -108,7 +113,8 @@ void objectBuilderTest() {
// 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!");
"The FlatBuffer was successfully created with an object builder and verified!",
);
}
}

View File

@@ -4,8 +4,8 @@
library my_game.sample;
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'package:flat_buffers/flat_buffers.dart' as fb;
class Color {
final int value;
@@ -19,7 +19,7 @@ class Color {
return result;
}
static Color? _createOrNull(int? value) =>
static Color? _createOrNull(int? value) =>
value == null ? null : Color.fromValue(value);
static const int minValue = 0;
@@ -29,10 +29,7 @@ class Color {
static const Color Red = Color._(0);
static const Color Green = Color._(1);
static const Color Blue = Color._(2);
static const Map<int, Color> values = {
0: Red,
1: Green,
2: Blue};
static const Map<int, Color> values = {0: Red, 1: Green, 2: Blue};
static const fb.Reader<Color> reader = _ColorReader();
@@ -60,12 +57,14 @@ class EquipmentTypeId {
factory EquipmentTypeId.fromValue(int value) {
final result = values[value];
if (result == null) {
throw StateError('Invalid value $value for bit flag enum EquipmentTypeId');
throw StateError(
'Invalid value $value for bit flag enum EquipmentTypeId',
);
}
return result;
}
static EquipmentTypeId? _createOrNull(int? value) =>
static EquipmentTypeId? _createOrNull(int? value) =>
value == null ? null : EquipmentTypeId.fromValue(value);
static const int minValue = 0;
@@ -74,9 +73,7 @@ class EquipmentTypeId {
static const EquipmentTypeId NONE = EquipmentTypeId._(0);
static const EquipmentTypeId Weapon = EquipmentTypeId._(1);
static const Map<int, EquipmentTypeId> values = {
0: NONE,
1: Weapon};
static const Map<int, EquipmentTypeId> values = {0: NONE, 1: Weapon};
static const fb.Reader<EquipmentTypeId> reader = _EquipmentTypeIdReader();
@@ -122,8 +119,7 @@ class _Vec3Reader extends fb.StructReader<Vec3> {
int get size => 12;
@override
Vec3 createObject(fb.BufferContext bc, int offset) =>
Vec3._(bc, offset);
Vec3 createObject(fb.BufferContext bc, int offset) => Vec3._(bc, offset);
}
class Vec3Builder {
@@ -137,7 +133,6 @@ class Vec3Builder {
fbBuilder.putFloat32(x);
return fbBuilder.offset;
}
}
class Vec3ObjectBuilder extends fb.ObjectBuilder {
@@ -145,14 +140,10 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
final double _y;
final double _z;
Vec3ObjectBuilder({
required double x,
required double y,
required double z,
})
: _x = x,
_y = y,
_z = z;
Vec3ObjectBuilder({required double x, required double y, required double z})
: _x = x,
_y = y,
_z = z;
/// Finish building, and store into the [fbBuilder].
@override
@@ -171,6 +162,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer;
}
}
class Monster {
Monster._(this._bc, this._bcOffset);
factory Monster(List<int> bytes) {
@@ -186,18 +178,30 @@ class Monster {
Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4);
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().vTableGetNullable(_bc, _bcOffset, 10);
List<int>? get inventory => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14);
Color get color => Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
List<Weapon>? get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGetNullable(_bc, _bcOffset, 18);
EquipmentTypeId? get equippedType => EquipmentTypeId._createOrNull(const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 20));
String? get name =>
const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10);
List<int>? get inventory =>
const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14);
Color get color =>
Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
List<Weapon>? get weapons => const fb.ListReader<Weapon>(
Weapon.reader,
).vTableGetNullable(_bc, _bcOffset, 18);
EquipmentTypeId? get equippedType => EquipmentTypeId._createOrNull(
const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 20),
);
dynamic get equipped {
switch (equippedType?.value) {
case 1: return Weapon.reader.vTableGetNullable(_bc, _bcOffset, 22);
default: return null;
case 1:
return Weapon.reader.vTableGetNullable(_bc, _bcOffset, 22);
default:
return null;
}
}
List<Vec3>? get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGetNullable(_bc, _bcOffset, 24);
List<Vec3>? get path => const fb.ListReader<Vec3>(
Vec3.reader,
).vTableGetNullable(_bc, _bcOffset, 24);
@override
String toString() {
@@ -209,8 +213,8 @@ class _MonsterReader extends fb.TableReader<Monster> {
const _MonsterReader();
@override
Monster createObject(fb.BufferContext bc, int offset) =>
Monster._(bc, offset);
Monster createObject(fb.BufferContext bc, int offset) =>
Monster._(bc, offset);
}
class MonsterBuilder {
@@ -226,38 +230,47 @@ class MonsterBuilder {
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;
@@ -291,29 +304,34 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
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;
}) : _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) {
final int? nameOffset = _name == null ? null
final int? nameOffset = _name == null
? null
: fbBuilder.writeString(_name!);
final int? inventoryOffset = _inventory == null ? null
final int? inventoryOffset = _inventory == null
? null
: fbBuilder.writeListUint8(_inventory!);
final int? weaponsOffset = _weapons == null ? null
: fbBuilder.writeList(_weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList());
final int? weaponsOffset = _weapons == null
? null
: fbBuilder.writeList(
_weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList(),
);
final int? equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
final int? pathOffset = _path == null ? null
final int? pathOffset = _path == null
? null
: fbBuilder.writeListOfStructs(_path!);
fbBuilder.startTable(10);
if (_pos != null) {
@@ -339,6 +357,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer;
}
}
class Weapon {
Weapon._(this._bc, this._bcOffset);
factory Weapon(List<int> bytes) {
@@ -351,7 +370,8 @@ class Weapon {
final fb.BufferContext _bc;
final int _bcOffset;
String? get name => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4);
String? get name =>
const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4);
int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 0);
@override
@@ -364,8 +384,7 @@ class _WeaponReader extends fb.TableReader<Weapon> {
const _WeaponReader();
@override
Weapon createObject(fb.BufferContext bc, int offset) =>
Weapon._(bc, offset);
Weapon createObject(fb.BufferContext bc, int offset) => Weapon._(bc, offset);
}
class WeaponBuilder {
@@ -381,6 +400,7 @@ class WeaponBuilder {
fbBuilder.addOffset(0, offset);
return fbBuilder.offset;
}
int addDamage(int? damage) {
fbBuilder.addInt16(1, damage);
return fbBuilder.offset;
@@ -395,17 +415,15 @@ class WeaponObjectBuilder extends fb.ObjectBuilder {
final String? _name;
final int? _damage;
WeaponObjectBuilder({
String? name,
int? damage,
})
: _name = name,
_damage = damage;
WeaponObjectBuilder({String? name, int? damage})
: _name = name,
_damage = damage;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
final int? nameOffset = _name == null ? null
final int? nameOffset = _name == null
? null
: fbBuilder.writeString(_name!);
fbBuilder.startTable(2);
fbBuilder.addOffset(0, nameOffset);

View File

@@ -27,10 +27,11 @@ class BufferContext {
ByteData get buffer => _buffer;
/// Create from a FlatBuffer represented by a list of bytes (uint8).
factory BufferContext.fromBytes(List<int> byteList) =>
BufferContext(byteList is Uint8List
? byteList.buffer.asByteData(byteList.offsetInBytes)
: ByteData.view(Uint8List.fromList(byteList).buffer));
factory BufferContext.fromBytes(List<int> byteList) => BufferContext(
byteList is Uint8List
? byteList.buffer.asByteData(byteList.offsetInBytes)
: ByteData.view(Uint8List.fromList(byteList).buffer),
);
/// Create from a FlatBuffer represented by ByteData.
BufferContext(this._buffer);
@@ -149,9 +150,9 @@ class Builder {
bool internStrings = false,
Allocator allocator = const DefaultAllocator(),
this.deduplicateTables = true,
}) : _allocator = allocator,
_buf = allocator.allocate(initialSize),
_vTables = deduplicateTables ? [] : const [] {
}) : _allocator = allocator,
_buf = allocator.allocate(initialSize),
_vTables = deduplicateTables ? [] : const [] {
if (internStrings) {
_strings = <String, int>{};
}
@@ -350,8 +351,10 @@ class Builder {
Uint8List get buffer {
assert(_finished);
final finishedSize = size();
return _buf.buffer
.asUint8List(_buf.lengthInBytes - finishedSize, finishedSize);
return _buf.buffer.asUint8List(
_buf.lengthInBytes - finishedSize,
finishedSize,
);
}
/// Finish off the creation of the buffer. The given [offset] is used as the
@@ -368,14 +371,18 @@ class Builder {
if (fileIdentifier != null) {
for (var i = 0; i < 4; i++) {
_setUint8AtTail(
finishedSize - _sizeofUint32 - i, fileIdentifier.codeUnitAt(i));
finishedSize - _sizeofUint32 - i,
fileIdentifier.codeUnitAt(i),
);
}
}
// zero out the added padding
for (var i = sizeBeforePadding + 1;
i <= finishedSize - requiredBytes;
i++) {
for (
var i = sizeBeforePadding + 1;
i <= finishedSize - requiredBytes;
i++
) {
_setUint8AtTail(i, 0);
}
_finished = true;
@@ -687,8 +694,10 @@ class Builder {
int writeString(String value, {bool asciiOptimization = false}) {
assert(!_inVTable);
if (_strings != null) {
return _strings!
.putIfAbsent(value, () => _writeString(value, asciiOptimization));
return _strings!.putIfAbsent(
value,
() => _writeString(value, asciiOptimization),
);
} else {
return _writeString(value, asciiOptimization);
}
@@ -1005,8 +1014,11 @@ class ListReader<E> extends Reader<List<E>> {
: List<E>.generate(
bc.buffer.getUint32(listOffset, Endian.little),
(int index) => _elementReader.read(
bc, listOffset + size + _elementReader.size * index),
growable: true);
bc,
listOffset + size + _elementReader.size * index,
),
growable: true,
);
}
}
@@ -1284,7 +1296,7 @@ class _FbGenericList<E> extends _FbList<E> {
List<E?>? _items;
_FbGenericList(this.elementReader, BufferContext bp, int offset)
: super(bp, offset);
: super(bp, offset);
@override
@pragma('vm:prefer-inline')
@@ -1454,7 +1466,11 @@ abstract class Allocator {
/// Params [inUseBack] and [inUseFront] indicate how much of [oldData] is
/// actually in use at each end, and needs to be copied.
ByteData resize(
ByteData oldData, int newSize, int inUseBack, int inUseFront) {
ByteData oldData,
int newSize,
int inUseBack,
int inUseFront,
) {
final newData = allocate(newSize);
_copyDownward(oldData, newData, inUseBack, inUseFront);
deallocate(oldData);
@@ -1465,17 +1481,25 @@ abstract class Allocator {
/// memory of size [inUseFront] and [inUseBack] will be copied from the front
/// and back of the old memory allocation.
void _copyDownward(
ByteData oldData, ByteData newData, int inUseBack, int inUseFront) {
ByteData oldData,
ByteData newData,
int inUseBack,
int inUseFront,
) {
if (inUseBack != 0) {
newData.buffer.asUint8List().setAll(
newData.lengthInBytes - inUseBack,
oldData.buffer.asUint8List().getRange(
oldData.lengthInBytes - inUseBack, oldData.lengthInBytes));
newData.lengthInBytes - inUseBack,
oldData.buffer.asUint8List().getRange(
oldData.lengthInBytes - inUseBack,
oldData.lengthInBytes,
),
);
}
if (inUseFront != 0) {
newData.buffer
.asUint8List()
.setAll(0, oldData.buffer.asUint8List().getRange(0, inUseFront));
newData.buffer.asUint8List().setAll(
0,
oldData.buffer.asUint8List().getRange(0, inUseFront),
);
}
}
}

View File

@@ -5,7 +5,7 @@ import 'types.dart';
/// The main builder class for creation of a FlexBuffer.
class Builder {
final ByteData _buffer;
ByteData _buffer;
List<_StackValue> _stack = [];
List<_StackPointer> _stackPointers = [];
int _offset = 0;
@@ -107,8 +107,11 @@ class Builder {
final newOffset = _newOffset(length + 1);
_pushBuffer(utf8String);
_offset = newOffset;
final stackValue =
_StackValue.withOffset(stringOffset, ValueType.String, bitWidth);
final stackValue = _StackValue.withOffset(
stringOffset,
ValueType.String,
bitWidth,
);
_stack.add(stackValue);
_stringCache[value] = stackValue;
}
@@ -128,8 +131,11 @@ class Builder {
final newOffset = _newOffset(length + 1);
_pushBuffer(utf8String);
_offset = newOffset;
final stackValue =
_StackValue.withOffset(keyOffset, ValueType.Key, BitWidth.width8);
final stackValue = _StackValue.withOffset(
keyOffset,
ValueType.Key,
BitWidth.width8,
);
_stack.add(stackValue);
_keyCache[value] = stackValue;
}
@@ -147,8 +153,11 @@ class Builder {
final newOffset = _newOffset(length);
_pushBuffer(value.asUint8List());
_offset = newOffset;
final stackValue =
_StackValue.withOffset(blobOffset, ValueType.Blob, bitWidth);
final stackValue = _StackValue.withOffset(
blobOffset,
ValueType.Blob,
bitWidth,
);
_stack.add(stackValue);
}
@@ -170,7 +179,10 @@ class Builder {
final valueOffset = _offset;
_pushBuffer(stackValue.asU8List(stackValue.width));
final stackOffset = _StackValue.withOffset(
valueOffset, ValueType.IndirectInt, stackValue.width);
valueOffset,
ValueType.IndirectInt,
stackValue.width,
);
_stack.add(stackOffset);
_offset = newOffset;
if (cache) {
@@ -195,7 +207,10 @@ class Builder {
final valueOffset = _offset;
_pushBuffer(stackValue.asU8List(stackValue.width));
final stackOffset = _StackValue.withOffset(
valueOffset, ValueType.IndirectFloat, stackValue.width);
valueOffset,
ValueType.IndirectFloat,
stackValue.width,
);
_stack.add(stackOffset);
_offset = newOffset;
if (cache) {
@@ -252,9 +267,10 @@ class Builder {
tmp._offset = _offset;
tmp._stack = List.from(_stack);
tmp._stackPointers = List.from(_stackPointers);
tmp._buffer.buffer
.asUint8List()
.setAll(0, _buffer.buffer.asUint8List(0, _offset));
tmp._buffer.buffer.asUint8List().setAll(
0,
_buffer.buffer.asUint8List(0, _offset),
);
for (var i = 0; i < tmp._stackPointers.length; i++) {
tmp.end();
}
@@ -271,7 +287,8 @@ class Builder {
if (_stackPointers.isNotEmpty && _stackPointers.last.isVector == false) {
if (_stack.last.type != ValueType.Key) {
throw StateError(
'Adding value to a map before adding a key is prohibited');
'Adding value to a map before adding a key is prohibited',
);
}
}
}
@@ -288,7 +305,8 @@ class Builder {
void _finish() {
if (_stack.length != 1) {
throw StateError(
'Stack has to be exactly 1, but is ${_stack.length}. You have to end all started vectors and maps, before calling [finish]');
'Stack has to be exactly 1, but is ${_stack.length}. You have to end all started vectors and maps, before calling [finish]',
);
}
final value = _stack[0];
final byteWidth = _align(value.elementWidth(_offset, 0));
@@ -298,8 +316,12 @@ class Builder {
_finished = true;
}
_StackValue _createVector(int start, int vecLength, int step,
[_StackValue? keys]) {
_StackValue _createVector(
int start,
int vecLength,
int step, [
_StackValue? keys,
]) {
var bitWidth = BitWidthUtil.uwidth(vecLength);
var prefixElements = 1;
if (keys != null) {
@@ -326,7 +348,8 @@ class Builder {
}
}
final byteWidth = _align(bitWidth);
final fix = typed & ValueTypeUtils.isNumber(vectorType) &&
final fix =
typed & ValueTypeUtils.isNumber(vectorType) &&
vecLength >= 2 &&
vecLength <= 4;
if (keys != null) {
@@ -349,8 +372,10 @@ class Builder {
return _StackValue.withOffset(vecOffset, ValueType.Map, bitWidth);
}
if (typed) {
final vType =
ValueTypeUtils.toTypedVector(vectorType, fix ? vecLength : 0);
final vType = ValueTypeUtils.toTypedVector(
vectorType,
fix ? vecLength : 0,
);
return _StackValue.withOffset(vecOffset, vType, bitWidth);
}
return _StackValue.withOffset(vecOffset, ValueType.Vector, bitWidth);
@@ -366,7 +391,8 @@ class Builder {
void _sortKeysAndEndMap(_StackPointer pointer) {
if (((_stack.length - pointer.stackPosition) & 1) == 1) {
throw StateError(
'The stack needs to hold key value pairs (even number of elements). Check if you combined [addKey] with add... method calls properly.');
'The stack needs to hold key value pairs (even number of elements). Check if you combined [addKey] with add... method calls properly.',
);
}
var sorted = true;
@@ -412,8 +438,12 @@ class Builder {
keysStackValue = _createVector(pointer.stackPosition, vecLength, 2);
_keyVectorCache[keysHash] = keysStackValue;
}
final vec =
_createVector(pointer.stackPosition + 1, vecLength, 2, keysStackValue);
final vec = _createVector(
pointer.stackPosition + 1,
vecLength,
2,
keysStackValue,
);
_stack.removeRange(pointer.stackPosition, _stack.length);
_stack.add(vec);
}
@@ -421,7 +451,8 @@ class Builder {
bool _shouldFlip(_StackValue v1, _StackValue v2) {
if (v1.type != ValueType.Key || v2.type != ValueType.Key) {
throw StateError(
'Stack values are not keys $v1 | $v2. Check if you combined [addKey] with add... method calls properly.');
'Stack values are not keys $v1 | $v2. Check if you combined [addKey] with add... method calls properly.',
);
}
late int c1, c2;
@@ -450,7 +481,8 @@ class Builder {
_writeUInt(relativeOffset, byteWidth);
} else {
throw StateError(
'Unexpected size $byteWidth. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
'Unexpected size $byteWidth. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new',
);
}
} else {
_pushBuffer(value.asU8List(BitWidthUtil.fromByteWidth(byteWidth)));
@@ -474,6 +506,7 @@ class Builder {
if (prevSize < size) {
final newBuf = ByteData(size);
newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List());
_buffer = newBuf;
}
return newOffset;
}
@@ -523,29 +556,27 @@ class _StackValue {
final ValueType _type;
final BitWidth _width;
_StackValue.withNull()
: _type = ValueType.Null,
_width = BitWidth.width8;
_StackValue.withNull() : _type = ValueType.Null, _width = BitWidth.width8;
_StackValue.withInt(int value)
: _type = ValueType.Int,
_width = BitWidthUtil.width(value),
_value = value;
: _type = ValueType.Int,
_width = BitWidthUtil.width(value),
_value = value;
_StackValue.withBool(bool value)
: _type = ValueType.Bool,
_width = BitWidth.width8,
_value = value;
: _type = ValueType.Bool,
_width = BitWidth.width8,
_value = value;
_StackValue.withDouble(double value)
: _type = ValueType.Float,
_width = BitWidthUtil.width(value),
_value = value;
: _type = ValueType.Float,
_width = BitWidthUtil.width(value),
_value = value;
_StackValue.withOffset(int value, ValueType type, BitWidth width)
: _offset = value,
_type = type,
_width = width;
: _offset = value,
_type = type,
_width = width;
BitWidth storedWidth({BitWidth width = BitWidth.width8}) {
return ValueTypeUtils.isInline(_type)
@@ -562,16 +593,16 @@ class _StackValue {
final offset = _offset!;
for (var i = 0; i < 4; i++) {
final width = 1 << i;
final bitWidth = BitWidthUtil.uwidth(size +
BitWidthUtil.paddingSize(size, width) +
index * width -
offset);
final bitWidth = BitWidthUtil.uwidth(
size + BitWidthUtil.paddingSize(size, width) + index * width - offset,
);
if (1 << bitWidth.index == width) {
return bitWidth;
}
}
throw StateError(
'Element is of unknown. Size: $size at index: $index. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
'Element is of unknown. Size: $size at index: $index. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new',
);
}
List<int> asU8List(BitWidth width) {
@@ -619,7 +650,8 @@ class _StackValue {
}
throw StateError(
'Unexpected type: $_type. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
'Unexpected type: $_type. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new',
);
}
ValueType get type {

View File

@@ -1,6 +1,7 @@
import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'types.dart';
/// Main class to read a value out of a FlexBuffer.
@@ -16,10 +17,15 @@ class Reference {
int? _length;
Reference._(
this._buffer, this._offset, this._parentWidth, int packedType, this._path,
[int? byteWidth, ValueType? valueType])
: _byteWidth = byteWidth ?? 1 << (packedType & 3),
_valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2);
this._buffer,
this._offset,
this._parentWidth,
int packedType,
this._path, [
int? byteWidth,
ValueType? valueType,
]) : _byteWidth = byteWidth ?? 1 << (packedType & 3),
_valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2);
/// Use this method to access the root value of a FlexBuffer.
static Reference fromBuffer(ByteBuffer buffer) {
@@ -31,8 +37,13 @@ class Reference {
final byteWidth = byteData.getUint8(len - 1);
final packedType = byteData.getUint8(len - 2);
final offset = len - byteWidth - 2;
return Reference._(ByteData.view(buffer), offset,
BitWidthUtil.fromByteWidth(byteWidth), packedType, "/");
return Reference._(
ByteData.view(buffer),
offset,
BitWidthUtil.fromByteWidth(byteWidth),
packedType,
"/",
);
}
/// Returns true if the underlying value is null.
@@ -138,7 +149,8 @@ class Reference {
final index = key;
if (index >= length || index < 0) {
throw ArgumentError(
'Key: [$key] is not applicable on: $_path of: $_valueType length: $length');
'Key: [$key] is not applicable on: $_path of: $_valueType length: $length',
);
}
final elementOffset = _indirect + index * _byteWidth;
int packedType = 0;
@@ -154,13 +166,14 @@ class Reference {
packedType = _buffer.getUint8(_indirect + length * _byteWidth + index);
}
return Reference._(
_buffer,
elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth),
packedType,
"$_path[$index]",
byteWidth,
valueType);
_buffer,
elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth),
packedType,
"$_path[$index]",
byteWidth,
valueType,
);
}
if (key is String && _valueType == ValueType.Map) {
final index = _keyIndex(key);
@@ -169,7 +182,8 @@ class Reference {
}
}
throw ArgumentError(
'Key: [$key] is not applicable on: $_path of: $_valueType');
'Key: [$key] is not applicable on: $_path of: $_valueType',
);
}
/// Get an iterable if the underlying flexBuffer value is a vector.
@@ -213,18 +227,24 @@ class Reference {
ValueTypeUtils.isAVector(_valueType) ||
_valueType == ValueType.Map) {
_length = _readUInt(
_indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
_indirect - _byteWidth,
BitWidthUtil.fromByteWidth(_byteWidth),
);
} else if (_valueType == ValueType.Null) {
_length = 0;
} else if (_valueType == ValueType.String) {
final indirect = _indirect;
var sizeByteWidth = _byteWidth;
var size = _readUInt(indirect - sizeByteWidth,
BitWidthUtil.fromByteWidth(sizeByteWidth));
var size = _readUInt(
indirect - sizeByteWidth,
BitWidthUtil.fromByteWidth(sizeByteWidth),
);
while (_buffer.getInt8(indirect + size) != 0) {
sizeByteWidth <<= 1;
size = _readUInt(indirect - sizeByteWidth,
BitWidthUtil.fromByteWidth(sizeByteWidth));
size = _readUInt(
indirect - sizeByteWidth,
BitWidthUtil.fromByteWidth(sizeByteWidth),
);
}
_length = size;
} else if (_valueType == ValueType.Key) {
@@ -289,7 +309,8 @@ class Reference {
return result.toString();
}
throw UnsupportedError(
'Type: $_valueType is not supported for JSON conversion');
'Type: $_valueType is not supported for JSON conversion',
);
}
/// Computes the indirect offset of the value.
@@ -354,10 +375,13 @@ class Reference {
int? _keyIndex(String key) {
final input = utf8.encode(key);
final keysVectorOffset = _indirect - _byteWidth * 3;
final indirectOffset = keysVectorOffset -
final indirectOffset =
keysVectorOffset -
_readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
final byteWidth = _readUInt(
keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
keysVectorOffset + _byteWidth,
BitWidthUtil.fromByteWidth(_byteWidth),
);
var low = 0;
var high = length - 1;
while (low <= high) {
@@ -390,24 +414,37 @@ class Reference {
final indirect = _indirect;
final elementOffset = indirect + index * _byteWidth;
final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
return Reference._(_buffer, elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key");
return Reference._(
_buffer,
elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth),
packedType,
"$_path/$key",
);
}
Reference _valueForIndex(int index) {
final indirect = _indirect;
final elementOffset = indirect + index * _byteWidth;
final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
return Reference._(_buffer, elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]");
return Reference._(
_buffer,
elementOffset,
BitWidthUtil.fromByteWidth(_byteWidth),
packedType,
"$_path/[$index]",
);
}
String _keyForIndex(int index) {
final keysVectorOffset = _indirect - _byteWidth * 3;
final indirectOffset = keysVectorOffset -
final indirectOffset =
keysVectorOffset -
_readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
final byteWidth = _readUInt(
keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
keysVectorOffset + _byteWidth,
BitWidthUtil.fromByteWidth(_byteWidth),
);
final keyOffset = indirectOffset + index * byteWidth;
final keyIndirectOffset =
keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));

View File

@@ -86,7 +86,8 @@ enum ValueType {
VectorFloat,
VectorKey,
@Deprecated(
'VectorString is deprecated due to a flaw in the binary format (https://github.com/google/flatbuffers/issues/5627)')
'VectorString is deprecated due to a flaw in the binary format (https://github.com/google/flatbuffers/issues/5627)',
)
VectorString,
VectorInt2,
VectorUInt2,
@@ -99,7 +100,7 @@ enum ValueType {
VectorFloat4,
Blob,
Bool,
VectorBool
VectorBool,
}
class ValueTypeUtils {
@@ -153,31 +154,37 @@ class ValueTypeUtils {
static ValueType toTypedVector(ValueType self, int length) {
if (length == 0) {
return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt));
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt),
);
}
if (length == 2) {
return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2));
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2),
);
}
if (length == 3) {
return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3));
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3),
);
}
if (length == 4) {
return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt4));
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt4),
);
}
throw Exception('unexpected length ' + length.toString());
}
static ValueType typedVectorElementType(ValueType self) {
return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int));
toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int),
);
}
static ValueType fixedTypedVectorElementType(ValueType self) {
return ValueTypeUtils.fromInt(
(toInt(self) - toInt(ValueType.VectorInt2)) % 3 + toInt(ValueType.Int));
(toInt(self) - toInt(ValueType.VectorInt2)) % 3 + toInt(ValueType.Int),
);
}
static int fixedTypedVectorElementSize(ValueType self) {

View File

@@ -1,5 +1,5 @@
name: flat_buffers
version: 25.1.21
version: 25.12.19
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
homepage: https://github.com/google/flatbuffers
documentation: https://google.github.io/flatbuffers/index.html

View File

@@ -2,8 +2,8 @@
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'package:flat_buffers/flat_buffers.dart' as fb;
class Foo {
Foo._(this._bc, this._bcOffset);
@@ -17,15 +17,15 @@ class Foo {
final fb.BufferContext _bc;
final int _bcOffset;
FooProperties? get myFoo => FooProperties.reader.vTableGetNullable(_bc, _bcOffset, 4);
FooProperties? get myFoo =>
FooProperties.reader.vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
return 'Foo{myFoo: ${myFoo}}';
}
FooT unpack() => FooT(
myFoo: myFoo?.unpack());
FooT unpack() => FooT(myFoo: myFoo?.unpack());
static int pack(fb.Builder fbBuilder, FooT? object) {
if (object == null) return 0;
@@ -36,8 +36,7 @@ class Foo {
class FooT implements fb.Packable {
FooPropertiesT? myFoo;
FooT({
this.myFoo});
FooT({this.myFoo});
@override
int pack(fb.Builder fbBuilder) {
@@ -58,8 +57,7 @@ class _FooReader extends fb.TableReader<Foo> {
const _FooReader();
@override
Foo createObject(fb.BufferContext bc, int offset) =>
Foo._(bc, offset);
Foo createObject(fb.BufferContext bc, int offset) => Foo._(bc, offset);
}
class FooBuilder {
@@ -84,10 +82,7 @@ class FooBuilder {
class FooObjectBuilder extends fb.ObjectBuilder {
final FooPropertiesObjectBuilder? _myFoo;
FooObjectBuilder({
FooPropertiesObjectBuilder? myFoo,
})
: _myFoo = myFoo;
FooObjectBuilder({FooPropertiesObjectBuilder? myFoo}) : _myFoo = myFoo;
/// Finish building, and store into the [fbBuilder].
@override
@@ -107,6 +102,7 @@ class FooObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer;
}
}
class FooProperties {
FooProperties._(this._bc, this._bcOffset);
@@ -123,9 +119,7 @@ class FooProperties {
return 'FooProperties{a: ${a}, b: ${b}}';
}
FooPropertiesT unpack() => FooPropertiesT(
a: a,
b: b);
FooPropertiesT unpack() => FooPropertiesT(a: a, b: b);
static int pack(fb.Builder fbBuilder, FooPropertiesT? object) {
if (object == null) return 0;
@@ -137,9 +131,7 @@ class FooPropertiesT implements fb.Packable {
bool a;
bool b;
FooPropertiesT({
required this.a,
required this.b});
FooPropertiesT({required this.a, required this.b});
@override
int pack(fb.Builder fbBuilder) {
@@ -161,8 +153,8 @@ class _FooPropertiesReader extends fb.StructReader<FooProperties> {
int get size => 2;
@override
FooProperties createObject(fb.BufferContext bc, int offset) =>
FooProperties._(bc, offset);
FooProperties createObject(fb.BufferContext bc, int offset) =>
FooProperties._(bc, offset);
}
class FooPropertiesBuilder {
@@ -175,19 +167,15 @@ class FooPropertiesBuilder {
fbBuilder.putBool(a);
return fbBuilder.offset;
}
}
class FooPropertiesObjectBuilder extends fb.ObjectBuilder {
final bool _a;
final bool _b;
FooPropertiesObjectBuilder({
required bool a,
required bool b,
})
: _a = a,
_b = b;
FooPropertiesObjectBuilder({required bool a, required bool b})
: _a = a,
_b = b;
/// Finish building, and store into the [fbBuilder].
@override

View File

@@ -2,8 +2,8 @@
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'package:flat_buffers/flat_buffers.dart' as fb;
enum OptionsEnum {
A(1),
@@ -15,10 +15,14 @@ enum OptionsEnum {
factory OptionsEnum.fromValue(int value) {
switch (value) {
case 1: return OptionsEnum.A;
case 2: return OptionsEnum.B;
case 3: return OptionsEnum.C;
default: throw StateError('Invalid value $value for bit flag enum');
case 1:
return OptionsEnum.A;
case 2:
return OptionsEnum.B;
case 3:
return OptionsEnum.C;
default:
throw StateError('Invalid value $value for bit flag enum');
}
}
@@ -53,7 +57,9 @@ class MyTable {
final fb.BufferContext _bc;
final int _bcOffset;
List<OptionsEnum>? get options => const fb.ListReader<OptionsEnum>(OptionsEnum.reader).vTableGetNullable(_bc, _bcOffset, 4);
List<OptionsEnum>? get options => const fb.ListReader<OptionsEnum>(
OptionsEnum.reader,
).vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
@@ -61,7 +67,11 @@ class MyTable {
}
MyTableT unpack() => MyTableT(
options: const fb.ListReader<OptionsEnum>(OptionsEnum.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 4));
options: const fb.ListReader<OptionsEnum>(
OptionsEnum.reader,
lazy: false,
).vTableGetNullable(_bc, _bcOffset, 4),
);
static int pack(fb.Builder fbBuilder, MyTableT? object) {
if (object == null) return 0;
@@ -72,12 +82,12 @@ class MyTable {
class MyTableT implements fb.Packable {
List<OptionsEnum>? options;
MyTableT({
this.options});
MyTableT({this.options});
@override
int pack(fb.Builder fbBuilder) {
final int? optionsOffset = options == null ? null
final int? optionsOffset = options == null
? null
: fbBuilder.writeListUint32(options!.map((f) => f.value).toList());
fbBuilder.startTable(1);
fbBuilder.addOffset(0, optionsOffset);
@@ -94,8 +104,8 @@ class _MyTableReader extends fb.TableReader<MyTable> {
const _MyTableReader();
@override
MyTable createObject(fb.BufferContext bc, int offset) =>
MyTable._(bc, offset);
MyTable createObject(fb.BufferContext bc, int offset) =>
MyTable._(bc, offset);
}
class MyTableBuilder {
@@ -120,15 +130,13 @@ class MyTableBuilder {
class MyTableObjectBuilder extends fb.ObjectBuilder {
final List<OptionsEnum>? _options;
MyTableObjectBuilder({
List<OptionsEnum>? options,
})
: _options = options;
MyTableObjectBuilder({List<OptionsEnum>? options}) : _options = options;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
final int? optionsOffset = _options == null ? null
final int? optionsOffset = _options == null
? null
: fbBuilder.writeListUint32(_options!.map((f) => f.value).toList());
fbBuilder.startTable(1);
fbBuilder.addOffset(0, optionsOffset);

View File

@@ -1,16 +1,15 @@
import 'dart:typed_data';
import 'dart:io' as io;
import 'package:path/path.dart' as path;
import 'dart:typed_data';
import 'package:flat_buffers/flat_buffers.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import './monster_test_my_game.example_generated.dart' as example;
import './monster_test_my_game.example2_generated.dart' as example2;
import 'enums_generated.dart' as example3;
import './bool_structs_generated.dart' as example4;
import './monster_test_my_game.example2_generated.dart' as example2;
import './monster_test_my_game.example_generated.dart' as example;
import 'enums_generated.dart' as example3;
main() {
defineReflectiveSuite(() {
@@ -29,11 +28,9 @@ int indexToField(int index) {
@reflectiveTest
class CheckOtherLangaugesData {
test_cppData() async {
List<int> data = await io.File(path.join(
path.context.current,
'test',
'monsterdata_test.mon',
)).readAsBytes();
List<int> data = await io.File(
path.join(path.context.current, 'test', 'monsterdata_test.mon'),
).readAsBytes();
example.Monster mon = example.Monster(data);
expect(mon.hp, 80);
expect(mon.mana, 150);
@@ -61,91 +58,92 @@ class CheckOtherLangaugesData {
// 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.Green, test3: Test{a: 5, b: 6}}, '
'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], '
'color: Color.Blue, testType: AnyTypeId.Monster, '
'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
'inventory: null, color: Color.Blue, testType: null, '
'test: null, test4: null, testarrayofstring: null, '
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
'testarrayofsortedstruct: null, flex: null, test5: null, '
'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
'vectorOfReferrables: null, singleWeakReference: 0, '
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
'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.Blue, testType: null, '
'test: null, test4: null, testarrayofstring: null, '
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
'testarrayofsortedstruct: null, flex: null, test5: null, '
'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
'vectorOfReferrables: null, singleWeakReference: 0, '
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
'testnestedflatbuffer: null, testempty: null, testbool: true, '
'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: ['
'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, '
'Ability{id: 5, distance: 12}], '
'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], '
'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], '
'parentNamespaceTest: null, vectorOfReferrables: null, '
'singleWeakReference: 0, vectorOfWeakReferences: null, '
'vectorOfStrongReferrables: null, coOwningReference: 0, '
'vectorOfCoOwningReferences: null, nonOwningReference: 0, '
'vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, '
'anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: '
'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
'nativeInline: Test{a: 1, b: 2}, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}');
mon.toString(),
'Monster{'
'pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color.Green, test3: Test{a: 5, b: 6}}, '
'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], '
'color: Color.Blue, testType: AnyTypeId.Monster, '
'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
'inventory: null, color: Color.Blue, testType: null, '
'test: null, test4: null, testarrayofstring: null, '
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
'testarrayofsortedstruct: null, flex: null, test5: null, '
'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
'vectorOfReferrables: null, singleWeakReference: 0, '
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
'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.Blue, testType: null, '
'test: null, test4: null, testarrayofstring: null, '
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
'testarrayofsortedstruct: null, flex: null, test5: null, '
'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
'vectorOfReferrables: null, singleWeakReference: 0, '
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
'testnestedflatbuffer: null, testempty: null, testbool: true, '
'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: ['
'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, '
'Ability{id: 5, distance: 12}], '
'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], '
'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], '
'parentNamespaceTest: null, vectorOfReferrables: null, '
'singleWeakReference: 0, vectorOfWeakReferences: null, '
'vectorOfStrongReferrables: null, coOwningReference: 0, '
'vectorOfCoOwningReferences: null, nonOwningReference: 0, '
'vectorOfNonOwningReferences: null, '
'anyUniqueType: null, anyUnique: null, '
'anyAmbiguousType: null, '
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, '
'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: '
'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
'nativeInline: Test{a: 1, b: 2}, '
'longEnumNonEnumDefault: LongEnum._default, '
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}',
);
}
}
@@ -298,20 +296,72 @@ class BuilderTest {
expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]);
builder.putUint8(3);
expect(
allocator.buffer(builder.size()), [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
0,
0,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint8(4);
expect(
allocator.buffer(builder.size()), [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
0,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint8(5);
expect(
allocator.buffer(builder.size()), [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
5,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint32(6);
expect(allocator.buffer(builder.size()),
[6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
6,
0,
0,
0,
0,
5,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
}
void test_table_default() {
@@ -331,14 +381,14 @@ class BuilderTest {
int objectOffset = buffer.derefObject(0);
// was not written, so uses the new default value
expect(
const Int32Reader()
.vTableGet(buffer, objectOffset, indexToField(0), 15),
15);
const Int32Reader().vTableGet(buffer, objectOffset, indexToField(0), 15),
15,
);
// has the written value
expect(
const Int32Reader()
.vTableGet(buffer, objectOffset, indexToField(1), 15),
20);
const Int32Reader().vTableGet(buffer, objectOffset, indexToField(1), 15),
20,
);
}
void test_table_format([Builder? builder]) {
@@ -370,7 +420,9 @@ class BuilderTest {
for (int i = 0; i < 3; i++) {
int offset = byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
expect(
byteData.getInt32(tableDataLoc + offset, Endian.little), 10 + 10 * i);
byteData.getInt32(tableDataLoc + offset, Endian.little),
10 + 10 * i,
);
}
}
@@ -380,10 +432,14 @@ class BuilderTest {
List<int> byteList;
{
Builder builder = Builder(initialSize: 0);
int? latinStringOffset =
builder.writeString(latinString, asciiOptimization: true);
int? unicodeStringOffset =
builder.writeString(unicodeString, asciiOptimization: true);
int? latinStringOffset = builder.writeString(
latinString,
asciiOptimization: true,
);
int? unicodeStringOffset = builder.writeString(
unicodeString,
asciiOptimization: true,
);
builder.startTable(2);
builder.addOffset(0, latinStringOffset);
builder.addOffset(1, unicodeStringOffset);
@@ -395,13 +451,19 @@ class BuilderTest {
BufferContext buf = BufferContext.fromBytes(byteList);
int objectOffset = buf.derefObject(0);
expect(
const StringReader()
.vTableGetNullable(buf, objectOffset, indexToField(0)),
latinString);
const StringReader().vTableGetNullable(
buf,
objectOffset,
indexToField(0),
),
latinString,
);
expect(
const StringReader(asciiOptimization: true)
.vTableGetNullable(buf, objectOffset, indexToField(1)),
unicodeString);
const StringReader(
asciiOptimization: true,
).vTableGetNullable(buf, objectOffset, indexToField(1)),
unicodeString,
);
}
void test_table_types([Builder? builder]) {
@@ -425,33 +487,41 @@ class BuilderTest {
BufferContext buf = BufferContext.fromBytes(byteList);
int objectOffset = buf.derefObject(0);
expect(
const BoolReader()
.vTableGetNullable(buf, objectOffset, indexToField(0)),
true);
const BoolReader().vTableGetNullable(buf, objectOffset, indexToField(0)),
true,
);
expect(
const Int8Reader()
.vTableGetNullable(buf, objectOffset, indexToField(1)),
10);
const Int8Reader().vTableGetNullable(buf, objectOffset, indexToField(1)),
10,
);
expect(
const Int32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(2)),
20);
const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(2)),
20,
);
expect(
const StringReader()
.vTableGetNullable(buf, objectOffset, indexToField(3)),
'12345');
const StringReader().vTableGetNullable(
buf,
objectOffset,
indexToField(3),
),
'12345',
);
expect(
const Int32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(4)),
40);
const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(4)),
40,
);
expect(
const Uint32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(5)),
0x9ABCDEF0);
const Uint32Reader().vTableGetNullable(
buf,
objectOffset,
indexToField(5),
),
0x9ABCDEF0,
);
expect(
const Uint8Reader()
.vTableGetNullable(buf, objectOffset, indexToField(6)),
0x9A);
const Uint8Reader().vTableGetNullable(buf, objectOffset, indexToField(6)),
0x9A,
);
}
void test_writeList_of_Uint32() {
@@ -596,8 +666,9 @@ class BuilderTest {
}
// read and verify
BufferContext buf = BufferContext.fromBytes(byteList);
List<TestPointImpl> items =
const ListReader<TestPointImpl>(TestPointReader()).read(buf, 0);
List<TestPointImpl> items = const ListReader<TestPointImpl>(
TestPointReader(),
).read(buf, 0);
expect(items, hasLength(2));
expect(items[0].x, 10);
expect(items[0].y, 20);
@@ -627,8 +698,10 @@ class BuilderTest {
List<int> byteList;
{
builder ??= Builder(initialSize: 0);
int listOffset = builder.writeList(
[builder.writeString('12345'), builder.writeString('ABC')]);
int listOffset = builder.writeList([
builder.writeString('12345'),
builder.writeString('ABC'),
]);
builder.startTable(1);
builder.addOffset(0, listOffset);
int offset = builder.endTable();
@@ -707,13 +780,14 @@ class BuilderTest {
test_table_format,
test_table_types,
test_writeList_ofObjects,
test_writeList_ofStrings_inObject
test_writeList_ofStrings_inObject,
];
// Execute all test cases in all permutations of their order.
// To do that, we generate permutations of test case indexes.
final testCasesPermutations =
_permutationsOf(List.generate(testCases.length, (index) => index));
final testCasesPermutations = _permutationsOf(
List.generate(testCases.length, (index) => index),
);
expect(testCasesPermutations.length, _factorial(testCases.length));
for (var indexes in testCasesPermutations) {
@@ -783,28 +857,28 @@ class ObjectAPITest {
void test_tableMonster() {
final monster = example.MonsterT()
..pos = example.Vec3T(
x: 1,
y: 2,
z: 3,
test1: 4.0,
test2: example.Color.Red,
test3: example.TestT(a: 1, b: 2))
x: 1,
y: 2,
z: 3,
test1: 4.0,
test2: example.Color.Red,
test3: example.TestT(a: 1, b: 2),
)
..mana = 2
..name = 'Monstrous'
..inventory = [24, 42]
..color = example.Color.Green
// TODO be smarter for unions and automatically set the `type` field?
..testType = example.AnyTypeId.MyGame_Example2_Monster
..test = example2.MonsterT()
..test4 = [example.TestT(a: 3, b: 4), example.TestT(a: 5, b: 6)]
..testarrayofstring = ["foo", "bar"]
..testarrayoftables = [example.MonsterT(name: 'Oof')]
..enemy = example.MonsterT(name: 'Enemy')
..testarrayoftables = [example.MonsterT(name: 'Oof', testf: 2.75)]
..enemy = example.MonsterT(name: 'Enemy', testf: 2.5)
..testarrayofbools = [false, true, false]
..testf = 42.24
..testf = 42.25
..testarrayofsortedstruct = [
example.AbilityT(id: 1, distance: 5),
example.AbilityT(id: 3, distance: 7)
example.AbilityT(id: 3, distance: 7),
]
..vectorOfLongs = [5, 6, 7]
..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2]
@@ -819,16 +893,15 @@ class ObjectAPITest {
fbBuilder.finish(offset);
final data = fbBuilder.buffer;
// TODO currently broken because of struct builder issue, see #6688
// final monster2 = example.Monster(data); // Monster (reader)
// expect(
// // map Monster => MonsterT, Vec3 => Vec3T, ...
// monster2.toString().replaceAllMapped(
// RegExp('([a-zA-z0-9]+){'), (match) => match.group(1) + 'T{'),
// monster.toString());
//
// final monster3 = monster2.unpack(); // MonsterT
// expect(monster3.toString(), monster.toString());
final monster2 = example.Monster(data); // Monster (reader)
expect(
// map Monster => MonsterT, Vec3 => Vec3T, ...
monster2.toString().replaceAllMapped(
RegExp('([a-zA-z0-9]+){'), (match) => match.group(1)! + 'T{'),
monster.toString());
final monster3 = monster2.unpack(); // MonsterT
expect(monster3.toString(), monster.toString());
}
void test_Lists() {
@@ -867,8 +940,9 @@ class StringListWrapperImpl {
StringListWrapperImpl(this.bp, this.offset);
List<String>? get items => const ListReader<String>(StringReader())
.vTableGetNullable(bp, offset, indexToField(0));
List<String>? get items => const ListReader<String>(
StringReader(),
).vTableGetNullable(bp, offset, indexToField(0));
}
class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
@@ -906,10 +980,14 @@ class GeneratorTest {
expect(example.Color.values, same(example.Color.values));
expect(example.Race.values, same(example.Race.values));
expect(example.AnyTypeId.values, same(example.AnyTypeId.values));
expect(example.AnyUniqueAliasesTypeId.values,
same(example.AnyUniqueAliasesTypeId.values));
expect(example.AnyAmbiguousAliasesTypeId.values,
same(example.AnyAmbiguousAliasesTypeId.values));
expect(
example.AnyUniqueAliasesTypeId.values,
same(example.AnyUniqueAliasesTypeId.values),
);
expect(
example.AnyAmbiguousAliasesTypeId.values,
same(example.AnyAmbiguousAliasesTypeId.values),
);
}
}
@@ -917,11 +995,13 @@ class GeneratorTest {
@reflectiveTest
class ListOfEnumsTest {
void test_listOfEnums() async {
var mytable = example3.MyTableObjectBuilder(options: [
example3.OptionsEnum.A,
example3.OptionsEnum.B,
example3.OptionsEnum.C
]);
var mytable = example3.MyTableObjectBuilder(
options: [
example3.OptionsEnum.A,
example3.OptionsEnum.B,
example3.OptionsEnum.C,
],
);
var bytes = mytable.toBytes();
var mytable_read = example3.MyTable(bytes);
expect(mytable_read.options![0].value, example3.OptionsEnum.A.value);
@@ -934,7 +1014,8 @@ class ListOfEnumsTest {
class BoolInStructTest {
void test_boolInStruct() async {
var mystruct = example4.FooObjectBuilder(
myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false));
myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false),
);
var bytes = mystruct.toBytes();
var mystruct_read = example4.Foo(bytes);
expect(mystruct_read.myFoo!.a, true);

View File

@@ -62,8 +62,23 @@ void main() {
{
var flx = Builder();
flx.addString('hello 😱');
expect(flx.finish(),
[10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]);
expect(flx.finish(), [
10,
104,
101,
108,
108,
111,
32,
240,
159,
152,
177,
0,
11,
20,
1,
]);
}
});
@@ -117,7 +132,7 @@ void main() {
192,
16,
75,
1
1,
]);
}
{
@@ -177,7 +192,7 @@ void main() {
7,
3,
60,
1
1,
]);
}
{
@@ -215,7 +230,7 @@ void main() {
10,
6,
60,
1
1,
]);
}
{
@@ -300,9 +315,24 @@ void main() {
104,
45,
43,
1
1,
]);
}
{
// Default buffer is 2048 bytes, add 2300 bytes of strings that force it
// to grow.
final s1 = 'A' * 1000;
final s2 = 'B' * 800;
final s3 = 'C' * 500;
var flx = Builder()
..startVector()
..addString(s1)
..addString(s2)
..addString(s3)
..end();
expect(flx.finish().length, 2323);
}
});
test('build map', () {
@@ -322,8 +352,24 @@ void main() {
..addKey('')
..addInt(45)
..end();
expect(
flx.finish(), [97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]);
expect(flx.finish(), [
97,
0,
0,
2,
2,
5,
2,
1,
2,
45,
12,
4,
4,
4,
36,
1,
]);
}
{
var flx = Builder()
@@ -367,7 +413,7 @@ void main() {
36,
4,
40,
1
1,
]);
}
});
@@ -381,133 +427,152 @@ void main() {
test('build from object', () {
expect(
Builder.buildFromObject(Uint8List.fromList([1, 2, 3]).buffer)
.asUint8List(),
[3, 1, 2, 3, 3, 100, 1]);
Builder.buildFromObject(
Uint8List.fromList([1, 2, 3]).buffer,
).asUint8List(),
[3, 1, 2, 3, 3, 100, 1],
);
expect(Builder.buildFromObject(null).asUint8List(), [0, 0, 1]);
expect(Builder.buildFromObject(true).asUint8List(), [1, 104, 1]);
expect(Builder.buildFromObject(false).asUint8List(), [0, 104, 1]);
expect(Builder.buildFromObject(25).asUint8List(), [25, 4, 1]);
expect(Builder.buildFromObject(-250).asUint8List(), [6, 255, 5, 2]);
expect(Builder.buildFromObject(-2.50).asUint8List(), [
0,
0,
32,
192,
14,
4,
]);
expect(Builder.buildFromObject('Maxim').asUint8List(), [
5,
77,
97,
120,
105,
109,
0,
6,
20,
1,
]);
expect(
Builder.buildFromObject(-2.50).asUint8List(), [0, 0, 32, 192, 14, 4]);
expect(Builder.buildFromObject('Maxim').asUint8List(),
[5, 77, 97, 120, 105, 109, 0, 6, 20, 1]);
Builder.buildFromObject([1, 3.3, 'max', true, null, false]).asUint8List(),
[
3,
109,
97,
120,
0,
0,
0,
0,
6,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
102,
102,
102,
102,
102,
102,
10,
64,
31,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
15,
20,
104,
0,
104,
54,
43,
1,
],
);
expect(
Builder.buildFromObject([1, 3.3, 'max', true, null, false])
.asUint8List(),
[
3,
109,
97,
120,
0,
0,
0,
0,
6,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
102,
102,
102,
102,
102,
102,
10,
64,
31,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
15,
20,
104,
0,
104,
54,
43,
1
]);
expect(
Builder.buildFromObject([
{'something': 12},
{'something': 45}
]).asUint8List(),
[
115,
111,
109,
101,
116,
104,
105,
110,
103,
0,
1,
11,
1,
1,
1,
12,
4,
6,
1,
1,
45,
4,
2,
8,
4,
36,
36,
4,
40,
1
]);
Builder.buildFromObject([
{'something': 12},
{'something': 45},
]).asUint8List(),
[
115,
111,
109,
101,
116,
104,
105,
110,
103,
0,
1,
11,
1,
1,
1,
12,
4,
6,
1,
1,
45,
4,
2,
8,
4,
36,
36,
4,
40,
1,
],
);
});
test('add double indirectly', () {
@@ -543,7 +608,7 @@ void main() {
35,
8,
40,
1
1,
]);
});
@@ -580,7 +645,7 @@ void main() {
27,
8,
40,
1
1,
]);
});

File diff suppressed because it is too large Load Diff

View File

@@ -48,116 +48,210 @@ void main() {
expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt), isFalse);
});
test('to typed vector', () {
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 0),
equals(ValueType.VectorInt));
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 0),
equals(ValueType.VectorUInt));
expect(ValueTypeUtils.toTypedVector(ValueType.Bool, 0),
equals(ValueType.VectorBool));
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 0),
equals(ValueType.VectorFloat));
expect(ValueTypeUtils.toTypedVector(ValueType.Key, 0),
equals(ValueType.VectorKey));
expect(ValueTypeUtils.toTypedVector(ValueType.String, 0),
equals(ValueType.VectorString));
expect(
ValueTypeUtils.toTypedVector(ValueType.Int, 0),
equals(ValueType.VectorInt),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.UInt, 0),
equals(ValueType.VectorUInt),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Bool, 0),
equals(ValueType.VectorBool),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 0),
equals(ValueType.VectorFloat),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Key, 0),
equals(ValueType.VectorKey),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.String, 0),
equals(ValueType.VectorString),
);
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 2),
equals(ValueType.VectorInt2));
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 2),
equals(ValueType.VectorUInt2));
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 2),
equals(ValueType.VectorFloat2));
expect(
ValueTypeUtils.toTypedVector(ValueType.Int, 2),
equals(ValueType.VectorInt2),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.UInt, 2),
equals(ValueType.VectorUInt2),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 2),
equals(ValueType.VectorFloat2),
);
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 3),
equals(ValueType.VectorInt3));
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 3),
equals(ValueType.VectorUInt3));
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 3),
equals(ValueType.VectorFloat3));
expect(
ValueTypeUtils.toTypedVector(ValueType.Int, 3),
equals(ValueType.VectorInt3),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.UInt, 3),
equals(ValueType.VectorUInt3),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 3),
equals(ValueType.VectorFloat3),
);
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 4),
equals(ValueType.VectorInt4));
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 4),
equals(ValueType.VectorUInt4));
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 4),
equals(ValueType.VectorFloat4));
expect(
ValueTypeUtils.toTypedVector(ValueType.Int, 4),
equals(ValueType.VectorInt4),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.UInt, 4),
equals(ValueType.VectorUInt4),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 4),
equals(ValueType.VectorFloat4),
);
});
test('typed vector element type', () {
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorInt),
equals(ValueType.Int));
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt),
equals(ValueType.UInt));
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat),
equals(ValueType.Float));
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorString),
equals(ValueType.String));
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorKey),
equals(ValueType.Key));
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorBool),
equals(ValueType.Bool));
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorInt),
equals(ValueType.Int),
);
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt),
equals(ValueType.UInt),
);
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat),
equals(ValueType.Float),
);
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorString),
equals(ValueType.String),
);
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorKey),
equals(ValueType.Key),
);
expect(
ValueTypeUtils.typedVectorElementType(ValueType.VectorBool),
equals(ValueType.Bool),
);
});
test('fixed typed vector element type', () {
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2),
equals(ValueType.Int));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3),
equals(ValueType.Int));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4),
equals(ValueType.Int));
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2),
equals(ValueType.Int),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3),
equals(ValueType.Int),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4),
equals(ValueType.Int),
);
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2),
equals(ValueType.UInt));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3),
equals(ValueType.UInt));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4),
equals(ValueType.UInt));
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2),
equals(ValueType.UInt),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3),
equals(ValueType.UInt),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4),
equals(ValueType.UInt),
);
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2),
equals(ValueType.Float));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3),
equals(ValueType.Float));
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4),
equals(ValueType.Float));
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2),
equals(ValueType.Float),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3),
equals(ValueType.Float),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4),
equals(ValueType.Float),
);
});
test('fixed typed vector element size', () {
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2),
equals(2));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3),
equals(3));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4),
equals(4));
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2),
equals(2),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4),
equals(4),
);
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2),
equals(2));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3),
equals(3));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4),
equals(4));
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2),
equals(2),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4),
equals(4),
);
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2),
equals(2));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3),
equals(3));
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4),
equals(4));
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2),
equals(2),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4),
equals(4),
);
});
test('packed type', () {
expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8), equals(0));
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8),
equals(0),
);
expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16), equals(1));
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16),
equals(1),
);
expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32), equals(2));
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32),
equals(2),
);
expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64), equals(3));
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64),
equals(3),
);
expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8), equals(4));
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8),
equals(4),
);
expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16), equals(5));
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16),
equals(5),
);
expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32), equals(6));
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32),
equals(6),
);
expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64), equals(7));
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64),
equals(7),
);
});
test('bit width', () {
expect(BitWidthUtil.width(0), BitWidth.width8);

View File

@@ -2,10 +2,11 @@
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './include_test2_my_game.other_name_space_generated.dart' as my_game_other_name_space;
import './include_test2_my_game.other_name_space_generated.dart'
as my_game_other_name_space;
class TableA {
TableA._(this._bc, this._bcOffset);
@@ -19,15 +20,17 @@ class TableA {
final fb.BufferContext _bc;
final int _bcOffset;
my_game_other_name_space.TableB? get b => my_game_other_name_space.TableB.reader.vTableGetNullable(_bc, _bcOffset, 4);
my_game_other_name_space.TableB? get b => my_game_other_name_space
.TableB
.reader
.vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
return 'TableA{b: ${b}}';
}
TableAT unpack() => TableAT(
b: b?.unpack());
TableAT unpack() => TableAT(b: b?.unpack());
static int pack(fb.Builder fbBuilder, TableAT? object) {
if (object == null) return 0;
@@ -38,8 +41,7 @@ class TableA {
class TableAT implements fb.Packable {
my_game_other_name_space.TableBT? b;
TableAT({
this.b});
TableAT({this.b});
@override
int pack(fb.Builder fbBuilder) {
@@ -59,8 +61,7 @@ class _TableAReader extends fb.TableReader<TableA> {
const _TableAReader();
@override
TableA createObject(fb.BufferContext bc, int offset) =>
TableA._(bc, offset);
TableA createObject(fb.BufferContext bc, int offset) => TableA._(bc, offset);
}
class TableABuilder {
@@ -85,10 +86,8 @@ class TableABuilder {
class TableAObjectBuilder extends fb.ObjectBuilder {
final my_game_other_name_space.TableBObjectBuilder? _b;
TableAObjectBuilder({
my_game_other_name_space.TableBObjectBuilder? b,
})
: _b = b;
TableAObjectBuilder({my_game_other_name_space.TableBObjectBuilder? b})
: _b = b;
/// Finish building, and store into the [fbBuilder].
@override

View File

@@ -4,8 +4,8 @@
library my_game.other_name_space;
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './include_test1_generated.dart';
@@ -17,8 +17,10 @@ enum FromInclude {
factory FromInclude.fromValue(int value) {
switch (value) {
case 0: return FromInclude.IncludeVal;
default: throw StateError('Invalid value $value for bit flag enum');
case 0:
return FromInclude.IncludeVal;
default:
throw StateError('Invalid value $value for bit flag enum');
}
}
@@ -56,8 +58,7 @@ class Unused {
return 'Unused{a: ${a}}';
}
UnusedT unpack() => UnusedT(
a: a);
UnusedT unpack() => UnusedT(a: a);
static int pack(fb.Builder fbBuilder, UnusedT? object) {
if (object == null) return 0;
@@ -68,8 +69,7 @@ class Unused {
class UnusedT implements fb.Packable {
int a;
UnusedT({
required this.a});
UnusedT({required this.a});
@override
int pack(fb.Builder fbBuilder) {
@@ -90,8 +90,7 @@ class _UnusedReader extends fb.StructReader<Unused> {
int get size => 4;
@override
Unused createObject(fb.BufferContext bc, int offset) =>
Unused._(bc, offset);
Unused createObject(fb.BufferContext bc, int offset) => Unused._(bc, offset);
}
class UnusedBuilder {
@@ -103,16 +102,12 @@ class UnusedBuilder {
fbBuilder.putInt32(a);
return fbBuilder.offset;
}
}
class UnusedObjectBuilder extends fb.ObjectBuilder {
final int _a;
UnusedObjectBuilder({
required int a,
})
: _a = a;
UnusedObjectBuilder({required int a}) : _a = a;
/// Finish building, and store into the [fbBuilder].
@override
@@ -129,6 +124,7 @@ class UnusedObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer;
}
}
class TableB {
TableB._(this._bc, this._bcOffset);
factory TableB(List<int> bytes) {
@@ -148,8 +144,7 @@ class TableB {
return 'TableB{a: ${a}}';
}
TableBT unpack() => TableBT(
a: a?.unpack());
TableBT unpack() => TableBT(a: a?.unpack());
static int pack(fb.Builder fbBuilder, TableBT? object) {
if (object == null) return 0;
@@ -160,8 +155,7 @@ class TableB {
class TableBT implements fb.Packable {
TableAT? a;
TableBT({
this.a});
TableBT({this.a});
@override
int pack(fb.Builder fbBuilder) {
@@ -181,8 +175,7 @@ class _TableBReader extends fb.TableReader<TableB> {
const _TableBReader();
@override
TableB createObject(fb.BufferContext bc, int offset) =>
TableB._(bc, offset);
TableB createObject(fb.BufferContext bc, int offset) => TableB._(bc, offset);
}
class TableBBuilder {
@@ -207,10 +200,7 @@ class TableBBuilder {
class TableBObjectBuilder extends fb.ObjectBuilder {
final TableAObjectBuilder? _a;
TableBObjectBuilder({
TableAObjectBuilder? a,
})
: _a = a;
TableBObjectBuilder({TableAObjectBuilder? a}) : _a = a;
/// Finish building, and store into the [fbBuilder].
@override

View File

@@ -7,6 +7,7 @@ import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
enum Abc {
$void(0),
where(1),
@@ -276,7 +277,7 @@ class Table2 {
Table2T unpack() => Table2T(
typeType: typeType,
type: type);
type: type?.unpack());
static int pack(fb.Builder fbBuilder, Table2T? object) {
if (object == null) return 0;

View File

@@ -4,12 +4,12 @@
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;
import './include_test1_generated.dart';
import './monster_test_my_game.example_generated.dart' as my_game_example;
import './monster_test_my_game_generated.dart' as my_game;
class Monster {
Monster._(this._bc, this._bcOffset);
@@ -23,7 +23,6 @@ class Monster {
final fb.BufferContext _bc;
final int _bcOffset;
@override
String toString() {
return 'Monster{}';
@@ -54,12 +53,11 @@ class _MonsterReader extends fb.TableReader<Monster> {
const _MonsterReader();
@override
Monster createObject(fb.BufferContext bc, int offset) =>
Monster._(bc, offset);
Monster createObject(fb.BufferContext bc, int offset) =>
Monster._(bc, offset);
}
class MonsterObjectBuilder extends fb.ObjectBuilder {
MonsterObjectBuilder();
/// Finish building, and store into the [fbBuilder].

File diff suppressed because it is too large Load Diff

View File

@@ -4,12 +4,12 @@
library my_game;
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_test_my_game.example_generated.dart' as my_game_example;
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
import './include_test1_generated.dart';
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);
@@ -23,7 +23,6 @@ class InParentNamespace {
final fb.BufferContext _bc;
final int _bcOffset;
@override
String toString() {
return 'InParentNamespace{}';
@@ -54,12 +53,11 @@ class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
const _InParentNamespaceReader();
@override
InParentNamespace createObject(fb.BufferContext bc, int offset) =>
InParentNamespace._(bc, offset);
InParentNamespace createObject(fb.BufferContext bc, int offset) =>
InParentNamespace._(bc, offset);
}
class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
InParentNamespaceObjectBuilder();
/// Finish building, and store into the [fbBuilder].

View File

@@ -1,3 +0,0 @@
This is the source of the old docs that are being replaced. They are served
from the `gh-pages-old` branch, while the new documentations (source in docs/)
is served from the `gh-pages` branch.

View File

@@ -1,14 +0,0 @@
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-49880327-7', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@@ -1,62 +0,0 @@
<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,700" rel="stylesheet">
$extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO-->
<td id="commonprojectlogo">
<img alt="Logo" src="$relpath^fpl_logo_small.png"/>
</td>
<!--BEGIN PROJECT_NAME-->
<td style="padding-left: 0.5em;">
<div id="projectname">$projectname
<!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
</div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td style="padding-left: 0.5em;">
<div id="projectbrief">$projectbrief</div>
</td>
<!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME-->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<td>$searchbox</td>
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,63 +0,0 @@
C++ Benchmarks {#flatbuffers_benchmarks}
==========
Comparing against other serialization solutions, running on Windows 7
64bit. We use the LITE runtime for Protocol Buffers (less code / lower
overhead), Rapid JSON (one of the fastest C++ JSON parsers around),
and pugixml, also one of the fastest XML parsers.
We also compare against code that doesn't use a serialization library
at all (the column "Raw structs"), which is what you get if you write
hardcoded code that just writes structs. This is the fastest possible,
but of course is not cross platform nor has any kind of forwards /
backwards compatibility.
We compare against Flatbuffers with the binary wire format (as
intended), and also with JSON as the wire format with the optional JSON
parser (which, using a schema, parses JSON into a binary buffer that can
then be accessed as before).
The benchmark object is a set of about 10 objects containing an array, 4
strings, and a large variety of int/float scalar values of all sizes,
meant to be representative of game data, e.g. a scene format.
| | FlatBuffers (binary) | Protocol Buffers LITE | Rapid JSON | FlatBuffers (JSON) | pugixml | Raw structs |
|--------------------------------------------------------|-----------------------|-----------------------|-----------------------|------------------------| ----------------------| ----------------------|
| Decode + Traverse + Dealloc (1 million times, seconds) | 0.08 | 302 | 583 | 105 | 196 | 0.02 |
| Decode / Traverse / Dealloc (breakdown) | 0 / 0.08 / 0 | 220 / 0.15 / 81 | 294 / 0.9 / 287 | 70 / 0.08 / 35 | 41 / 3.9 / 150 | 0 / 0.02 / 0 |
| Encode (1 million times, seconds) | 3.2 | 185 | 650 | 169 | 273 | 0.15 |
| Wire format size (normal / zlib, bytes) | 344 / 220 | 228 / 174 | 1475 / 322 | 1029 / 298 | 1137 / 341 | 312 / 187 |
| Memory needed to store decoded wire (bytes / blocks) | 0 / 0 | 760 / 20 | 65689 / 4 | 328 / 1 | 34194 / 3 | 0 / 0 |
| Transient memory allocated during decode (KB) | 0 | 1 | 131 | 4 | 34 | 0 |
| Generated source code size (KB) | 4 | 61 | 0 | 4 | 0 | 0 |
| Field access in handwritten traversal code | typed accessors | typed accessors | manual error checking | typed accessors | manual error checking | typed but no safety |
| Library source code (KB) | 15 | some subset of 3800 | 87 | 43 | 327 | 0 |
### Some other serialization systems we compared against but did not benchmark (yet), in rough order of applicability:
- Cap'n'Proto promises to reduce Protocol Buffers much like FlatBuffers does,
though with a more complicated binary encoding and less flexibility (no
optional fields to allow deprecating fields or serializing with missing
fields for which defaults exist).
It currently also isn't fully cross-platform portable (lack of VS support).
- msgpack: has very minimal forwards/backwards compatibility support when used
with the typed C++ interface. Also lacks VS2010 support.
- Thrift: very similar to Protocol Buffers, but appears to be less efficient,
and have more dependencies.
- YAML: a superset of JSON and otherwise very similar. Used by e.g. Unity.
- C# comes with built-in serialization functionality, as used by Unity also.
Being tied to the language, and having no automatic versioning support
limits its applicability.
- Project Anarchy (the free mobile engine by Havok) comes with a serialization
system, that however does no automatic versioning (have to code around new
fields manually), is very much tied to the rest of the engine, and works
without a schema to generate code (tied to your C++ class definition).
### Code for benchmarks
Code for these benchmarks sits in `benchmarks/` in git branch `benchmarks`.
It sits in its own branch because it has submodule dependencies that the main
project doesn't need, and the code standards do not meet those of the main
project. Please read `benchmarks/cpp/README.txt` before working with the code.
<br>

View File

@@ -1,134 +0,0 @@
Building {#flatbuffers_guide_building}
========
## Building with CMake
The distribution comes with a `cmake` file that should allow
you to build project/make files for any platform. For details on `cmake`, see
<https://www.cmake.org>. In brief, depending on your platform, use one of
e.g.:
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Release
cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release
Then, build as normal for your platform. This should result in a `flatc`
executable, essential for the next steps.
Note that to use clang instead of gcc, you may need to set up your environment
variables, e.g.
`CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -G "Unix Makefiles"`.
Optionally, run the `flattests` executable from the root `flatbuffers/`
directory to ensure everything is working correctly on your system. If this
fails, please contact us!
Building should also produce two sample executables, `flatsamplebinary` and
`flatsampletext`, see the corresponding `.cpp` files in the
`flatbuffers/samples` directory.
*Note that you MUST be in the root of the FlatBuffers distribution when you
run 'flattests' or `flatsampletext`, or it will fail to load its files.*
### Make all warnings into errors
By default all Flatbuffers `cmake` targets are **not** built with the `-Werror`
(or `/WX` for MSVC) flag that treats any warning as an error. This allows more
flexibility for users of Flatbuffers to use newer compilers and toolsets that
may add new warnings that would cause a build failure.
To enable a stricter build that does treat warnings as errors, set the
`FLATBUFFERS_STRICT_MODE` `cmake` compliation flag to `ON`.
```
cmake . -DFLATBUFFERS_STRICT_MODE=ON
```
Our CI builds run with strict mode on, ensuring the code that is committed to
the project is as portable and warning free as possible. Thus developers
contributing to the project should enable strict mode locally before making a
PR.
## Building with VCPKG
You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install flatbuffers
The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors.
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
## Downloading binaries
You can download the binaries from the
[GitHub release page](https://github.com/google/flatbuffers/releases).
We generate [SLSA3 signatures](slsa.dev) using the OpenSSF's [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). To verify the binaries:
1. Install the verification tool from [slsa-framework/slsa-verifier#installation](https://github.com/slsa-framework/slsa-verifier#installation)
1. Download the file named `attestation.intoto.jsonl` from the GitHub release
1. Run:
```shell
$ slsa-verifier -artifact-path <downloaded.zip> -provenance attestation.intoto.jsonl -source github.com/google/flatbuffers -tag <version>
PASSED: Verified SLSA provenance
```
## Building for Android
There is a `flatbuffers/android` directory that contains all you need to build
the test executable on android (use the included `build_apk.sh` script, or use
`ndk_build` / `adb` etc. as usual). Upon running, it will output to the log
if tests succeeded or not.
You may also run an android sample from inside the `flatbuffers/samples`, by
running the `android_sample.sh` script. Optionally, you may go to the
`flatbuffers/samples/android` folder and build the sample with the
`build_apk.sh` script or `ndk_build` / `adb` etc.
## Using FlatBuffers in your own projects
For C++, there is usually no runtime to compile, as the code consists of a
single header, `include/flatbuffers/flatbuffers.h`. You should add the
`include` folder to your include paths. If you wish to be
able to load schemas and/or parse text into binary buffers at runtime,
you additionally need the other headers in `include/flatbuffers`. You must
also compile/link `src/idl_parser.cpp` (and `src/idl_gen_text.cpp` if you
also want to be able convert binary to text).
To see how to include FlatBuffers in any of our supported languages, please
view the [Tutorial](@ref flatbuffers_guide_tutorial) and select your appropriate
language using the radio buttons.
### Using in CMake-based projects
If you want to use FlatBuffers in a project which already uses CMake, then a more
robust and flexible approach is to build FlatBuffers as part of that project directly.
This is done by making the FlatBuffers source code available to the main build
and adding it using CMake's `add_subdirectory()` command. This has the
significant advantage that the same compiler and linker settings are used
between FlatBuffers and the rest of your project, so issues associated with using
incompatible libraries (eg debug/release), etc. are avoided. This is
particularly useful on Windows.
Suppose you put FlatBuffers source code in directory `${FLATBUFFERS_SRC_DIR}`.
To build it as part of your project, add following code to your `CMakeLists.txt` file:
```cmake
# Add FlatBuffers directly to our build. This defines the `flatbuffers` target.
add_subdirectory(${FLATBUFFERS_SRC_DIR}
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
EXCLUDE_FROM_ALL)
# Now simply link against flatbuffers as needed to your already declared target.
# The flatbuffers target carry header search path automatically if CMake > 2.8.11.
target_link_libraries(own_project_target PRIVATE flatbuffers)
```
When build your project the `flatbuffers` library will be compiled and linked
to a target as part of your project.
#### Override default depth limit of nested objects
To override [the depth limit of recursion](@ref flatbuffers_guide_use_cpp),
add this directive:
```cmake
set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
```
to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line.

View File

@@ -1 +0,0 @@
../../CONTRIBUTING.md

View File

@@ -1,224 +0,0 @@
Use in C {#flatbuffers_guide_use_c}
==========
The C language binding exists in a separate project named [FlatCC](https://github.com/dvidelabs/flatcc).
The `flatcc` C schema compiler can generate code offline as well as
online via a C library. It can also generate buffer verifiers and fast
JSON parsers, printers.
Great care has been taken to ensure compatibility with the main `flatc`
project.
## General Documention
- [Tutorial](@ref flatbuffers_guide_tutorial) - select C as language
when scrolling down
- [FlatCC Guide](https://github.com/dvidelabs/flatcc#flatcc-flatbuffers-in-c-for-c)
- [The C Builder Interface](https://github.com/dvidelabs/flatcc/blob/master/doc/builder.md#the-builder-interface)
- [The Monster Sample in C](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c)
- [GitHub](https://github.com/dvidelabs/flatcc)
## Supported Platforms
- Ubuntu (clang / gcc, ninja / gnu make)
- OS-X (clang / gcc, ninja / gnu make)
- Windows MSVC 2010, 2013, 2015
CI builds recent versions of gcc, clang and MSVC on OS-X, Ubuntu, and
Windows, and occasionally older compiler versions. See main project [Status](https://github.com/dvidelabs/flatcc#status).
Other platforms may well work, including Centos, but are not tested
regularly.
The monster sample project was specifically written for C99 in order to
follow the C++ version and for that reason it will not work with MSVC
2010.
## Modular Object Creation
In the tutorial we used the call `Monster_create_as_root` to create the
root buffer object since this is easier in simple use cases. Sometimes
we need more modularity so we can reuse a function to create nested
tables and root tables the same way. For this we need the
`flatcc_builder_buffer_create_call`. It is best to keep `flatcc_builder`
calls isolated at the top driver level, so we get:
<div class="language-c">
~~~{.c}
ns(Monster_ref_t) create_orc(flatcc_builder_t *B)
{
// ... same as in the tutorial.
return s(Monster_create(B, ...));
}
void create_monster_buffer()
{
uint8_t *buf;
size_t size;
flatcc_builder_t builder, *B;
// Initialize the builder object.
B = &builder;
flatcc_builder_init(B);
// Only use `buffer_create` without `create/start/end_as_root`.
flatcc_builder_buffer_create(create_orc(B));
// Allocate and copy buffer to user memory.
buf = flatcc_builder_finalize_buffer(B, &size);
// ... write the buffer to disk or network, or something.
free(buf);
flatcc_builder_clear(B);
}
~~~
</div>
The same principle applies with `start/end` vs `start/end_as_root` in
the top-down approach.
## Top Down Example
The tutorial uses a bottom up approach. In C it is also possible to use
a top-down approach by starting and ending objects nested within each
other. In the tutorial there is no deep nesting, so the difference is
limited, but it shows the idea:
<div class="language-c">
<br>
~~~{.c}
uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
size_t treasure_count = c_vec_len(treasure);
ns(Weapon_ref_t) axe;
// NOTE: if we use end_as_root, we MUST also start as root.
ns(Monster_start_as_root(B));
ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
ns(Monster_hp_add(B, 300));
ns(Monster_mana_add(B, 150));
// We use create_str instead of add because we have no existing string reference.
ns(Monster_name_create_str(B, "Orc"));
// Again we use create because we no existing vector object, only a C-array.
ns(Monster_inventory_create(B, treasure, treasure_count));
ns(Monster_color_add(B, ns(Color_Red)));
if (1) {
ns(Monster_weapons_start(B));
ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3));
// We reuse the axe object later. Note that we dereference a pointer
// because push always returns a short-term pointer to the stored element.
// We could also have created the axe object first and simply pushed it.
axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5));
ns(Monster_weapons_end(B));
} else {
// We can have more control with the table elements added to a vector:
//
ns(Monster_weapons_start(B));
ns(Monster_weapons_push_start(B));
ns(Weapon_name_create_str(B, "Sword"));
ns(Weapon_damage_add(B, 3));
ns(Monster_weapons_push_end(B));
ns(Monster_weapons_push_start(B));
ns(Monster_weapons_push_start(B));
ns(Weapon_name_create_str(B, "Axe"));
ns(Weapon_damage_add(B, 5));
axe = *ns(Monster_weapons_push_end(B));
ns(Monster_weapons_end(B));
}
// Unions can get their type by using a type-specific add/create/start method.
ns(Monster_equipped_Weapon_add(B, axe));
ns(Monster_end_as_root(B));
~~~
</div>
## Basic Reflection
The C-API does support reading binary schema (.bfbs)
files via code generated from the `reflection.fbs` schema, and an
[example usage](https://github.com/dvidelabs/flatcc/tree/master/samples/reflection)
shows how to use this. The reflection schema files are pre-generated
in the [runtime distribution](https://github.com/dvidelabs/flatcc/tree/master/include/flatcc/reflection).
## Mutations and Reflection
The C-API does not support mutating reflection like C++ does, nor does
the reader interface support mutating scalars (and it is generally
unsafe to do so even after verification).
The generated reader interface supports sorting vectors in-place after
casting them to a mutating type because it is not practical to do so
while building a buffer. This is covered in the builder documentation.
The reflection example makes use of this feature to look up objects by
name.
It is possible to build new buffers using complex objects from existing
buffers as source. This can be very efficient due to direct copy
semantics without endian conversion or temporary stack allocation.
Scalars, structs and strings can be used as source, as well vectors of
these.
It is currently not possible to use an existing table or vector of table
as source, but it would be possible to add support for this at some
point.
## Namespaces
The `FLATBUFFERS_WRAP_NAMESPACE` approach used in the tutorial is convenient
when each function has a very long namespace prefix. But it isn't always
the best approach. If the namespace is absent, or simple and
informative, we might as well use the prefix directly. The
[reflection example](https://github.com/dvidelabs/flatcc/blob/master/samples/reflection/bfbs2json.c)
mentioned above uses this approach.
## Checking for Present Members
Not all languages support testing if a field is present, but in C we can
elaborate the reader section of the tutorial with tests for this. Recall
that `mana` was set to the default value `150` and therefore shouldn't
be present.
<div class="language-c">
~~~{.c}
int hp_present = ns(Monster_hp_is_present(monster)); // 1
int mana_present = ns(Monster_mana_is_present(monster)); // 0
~~~
</div>
## Alternative ways to add a Union
In the tutorial we used a single call to add a union. Here we show
different ways to accomplish the same thing. The last form is rarely
used, but is the low-level way to do it. It can be used to group small
values together in the table by adding type and data at different
points in time.
<div class="language-c">
~~~{.c}
ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
ns(Monster_equipped_add(B, equipped));
// or alternatively
ns(Monster_equipped_Weapon_add(B, axe);
// or alternatively
ns(Monster_equipped_add_type(B, ns(Equipment_Weapon));
ns(Monster_equipped_add_member(B, axe));
~~~
</div>
## Why not integrate with the `flatc` tool?
[It was considered how the C code generator could be integrated into the
`flatc` tool](https://github.com/dvidelabs/flatcc/issues/1), but it
would either require that the standalone C implementation of the schema
compiler was dropped, or it would lead to excessive code duplication, or
a complicated intermediate representation would have to be invented.
Neither of these alternatives are very attractive, and it isn't a big
deal to use the `flatcc` tool instead of `flatc` given that the
FlatBuffers C runtime library needs to be made available regardless.

View File

@@ -1,281 +0,0 @@
Using the schema compiler {#flatbuffers_guide_using_schema_compiler}
=========================
Usage:
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] FILES...
[ -- FILES...]
The files are read and parsed in order, and can contain either schemas
or data (see below). Data files are processed according to the definitions of
the most recent schema specified.
`--` indicates that the following files are binary files in
FlatBuffer format conforming to the schema indicated before it.
Depending on the flags passed, additional files may
be generated for each file processed:
For any schema input files, one or more generators can be specified:
- `--cpp`, `-c` : Generate a C++ header for all definitions in this file (as
`filename_generated.h`).
- `--java`, `-j` : Generate Java code.
- `--kotlin` , `--kotlin-kmp` : Generate Kotlin code.
- `--csharp`, `-n` : Generate C# code.
- `--go`, `-g` : Generate Go code.
- `--python`, `-p` : Generate Python code.
- `--js`, `-s` : Generate JavaScript code.
- `--ts`, `-T` : Generate TypeScript code.
- `--php` : Generate PHP code.
- `--grpc` : Generate RPC stub code for GRPC.
- `--dart`, `-d` : Generate Dart code.
- `--lua`, `-l` : Generate Lua code.
- `--lobster` : Generate Lobster code.
- `--rust`, `-r` : Generate Rust code.
- `--swift` : Generate Swift code.
- `--nim` : Generate Nim code.
For any data input files:
- `--binary`, `-b` : If data is contained in this file, generate a
`filename.bin` containing the binary flatbuffer (or a different extension
if one is specified in the schema).
- `--json`, `-t` : If data is contained in this file, generate a
`filename.json` representing the data in the flatbuffer.
- `--jsonschema` : Generate Json schema
Additional options:
- `-o PATH` : Output all generated files to PATH (either absolute, or
relative to the current directory). If omitted, PATH will be the
current directory. PATH should end in your systems path separator,
e.g. `/` or `\`.
- `-I PATH` : when encountering `include` statements, attempt to load the
files from this path. Paths will be tried in the order given, and if all
fail (or none are specified) it will try to load relative to the path of
the schema file being parsed.
- `-M` : Print make rules for generated files.
- `--strict-json` : Require & generate strict JSON (field names are enclosed
in quotes, no trailing commas in tables/vectors). By default, no quotes are
required/generated, and trailing commas are allowed.
- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
\x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
By default, UTF-8 characters are printed as \uXXXX escapes."
- `--defaults-json` : Output fields whose value is equal to the default value
when writing JSON text.
- `--no-prefix` : Don't prefix enum values in generated C++ by their enum
type.
- `--scoped-enums` : Use C++11 style scoped and strongly typed enums in
generated C++. This also implies `--no-prefix`.
- `--no-emit-min-max-enum-values` : Disable generation of MIN and MAX
enumerated values for scoped enums and prefixed enums.
- `--gen-includes` : (deprecated), this is the default behavior.
If the original behavior is required (no include
statements) use `--no-includes.`
- `--no-includes` : Don't generate include statements for included schemas the
generated file depends on (C++ / Python).
- `--gen-mutable` : Generate additional non-const accessors for mutating
FlatBuffers in-place.
- `--gen-onefile` : Generate single output file for C#, Go, and Python.
- `--gen-name-strings` : Generate type name functions for C++.
- `--gen-object-api` : Generate an additional object-based API. This API is
more convenient for object construction and mutation than the base API,
at the cost of efficiency (object allocation). Recommended only to be used
if other options are insufficient.
- `--gen-compare` : Generate operator== for object-based API types.
- `--gen-nullable` : Add Clang \_Nullable for C++ pointer. or @Nullable for Java.
- `--gen-generated` : Add @Generated annotation for Java.
- `--gen-jvmstatic` : Add @JvmStatic annotation for Kotlin methods
in companion object for interop from Java to Kotlin.
- `--gen-all` : Generate not just code for the current schema files, but
for all files it includes as well. If the language uses a single file for
output (by default the case for C++ and JS), all code will end up in
this one file.
- `--cpp-include` : Adds an #include in generated file
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
- `--cpp-str-type T` : Set object API string type (default std::string)
T::c_str(), T::length() and T::empty() must be supported.
The custom type also needs to be constructible from std::string (see the
--cpp-str-flex-ctor option to change this behavior).
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
std::string from Flatbuffers, but (char* + length). This allows efficient
construction of custom string types, including zero-copy construction.
- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
object-based API.
- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard.
Supported `CPP_STD` values:
* `c++0x` - generate code compatible with old compilers (VS2010),
* `c++11` - use C++11 code generator (default),
* `c++17` - use C++17 features in generated code (experimental).
- `--object-prefix` : Customise class prefix for C++ object-based API.
- `--object-suffix` : Customise class suffix for C++ object-based API.
- `--go-namespace` : Generate the overrided namespace in Golang.
- `--go-import` : Generate the overrided import for flatbuffers in Golang.
(default is "github.com/google/flatbuffers/go").
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
This may crash flatc given a mismatched schema.
- `--size-prefixed` : Input binaries are size prefixed buffers.
- `--proto`: Expect input files to be .proto files (protocol buffers).
Output the corresponding .fbs file.
Currently supports: `package`, `message`, `enum`, nested declarations,
`import` (use `-I` for paths), `extend`, `oneof`, `group`.
Does not support, but will skip without error: `option`, `service`,
`extensions`, and most everything else.
- `--oneof-union` : Translate .proto oneofs to flatbuffer unions.
- `--grpc` : Generate GRPC interfaces for the specified languages.
- `--schema`: Serialize schemas instead of JSON (use with -b). This will
output a binary version of the specified schema that itself corresponds
to the reflection/reflection.fbs schema. Loading this binary file is the
basis for reflection functionality.
- `--bfbs-comments`: Add doc comments to the binary schema files.
- `--conform FILE` : Specify a schema the following schemas should be
an evolution of. Gives errors if not. Useful to check if schema
modifications don't break schema evolution rules.
- `--conform-includes PATH` : Include path for the schema given with
`--conform PATH`.
- `--filename-suffix SUFFIX` : The suffix appended to the generated
file names. Default is '\_generated'.
- `--filename-ext EXTENSION` : The extension appended to the generated
file names. Default is language-specific (e.g. "h" for C++). This
should not be used when multiple languages are specified.
- `--include-prefix PATH` : Prefix this path to any generated include
statements.
- `--keep-prefix` : Keep original prefix of schema include statement.
- `--reflect-types` : Add minimal type reflection to code generation.
- `--reflect-names` : Add minimal type/name reflection.
- `--root-type T` : Select or override the default root_type.
- `--require-explicit-ids` : When parsing schemas, require explicit ids (id: x).
- `--force-defaults` : Emit default values in binary output from JSON.
- `--force-empty` : When serializing from object API representation, force
strings and vectors to empty rather than null.
- `--force-empty-vectors` : When serializing from object API representation, force
vectors to empty rather than null.
- `--flexbuffers` : Used with "binary" and "json" options, it generates
data using schema-less FlexBuffers.
- `--no-warnings` : Inhibit all warning messages.
- `--cs-global-alias` : Prepend `global::` to all user generated csharp classes and structs.
- `--json-nested-bytes` : Allow a nested_flatbuffer field to be parsed as a
vector of bytes in JSON, which is unsafe unless checked by a verifier
afterwards.
- `--python-no-type-prefix-suffix` : Skip emission of Python functions that are prefixed
with typenames
- `--python-typing` : Generate Python type annotations
Additional gRPC options:
- `--grpc-filename-suffix`: `[C++]` An optional suffix for the generated
files' names. For example, compiling gRPC for C++ with
`--grpc-filename-suffix=.fbs` will generate `{name}.fbs.h` and
`{name}.fbs.cc` files.
- `--grpc-additional-header`: `[C++]` Additional headers to include in the
generated files.
- `--grpc-search-path`: `[C++]` An optional prefix for the gRPC runtime path.
For example, compiling gRPC for C++ with `--grpc-search-path=some/path` will
generate the following includes:
```cpp
#include "some/path/grpcpp/impl/codegen/async_stream.h"
#include "some/path/grpcpp/impl/codegen/async_unary_call.h"
#include "some/path/grpcpp/impl/codegen/method_handler.h"
...
```
- `--grpc-use-system-headers`: `[C++]` Whether to generate `#include <header>`
instead of `#include "header.h"` for all headers when compiling gRPC for
C++. For example, compiling gRPC for C++ with `--grpc-use-system-headers`
will generate the following includes:
```cpp
#include <some/path/grpcpp/impl/codegen/async_stream.h>
#include <some/path/grpcpp/impl/codegen/async_unary_call.h>
#include <some/path/grpcpp/impl/codegen/method_handler.h>
...
```
NOTE: This option can be negated with `--no-grpc-use-system-headers`.
- `--grpc-python-typed-handlers`: `[Python]` Whether to generate the typed
handlers that use the generated Python classes instead of raw bytes for
requests/responses.
NOTE: short-form options for generators are deprecated, use the long form
whenever possible.

View File

@@ -1,639 +0,0 @@
Use in C++ {#flatbuffers_guide_use_cpp}
==========
## Before you get started
Before diving into the FlatBuffers usage in C++, 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 C++).
This page is designed to cover the nuances of FlatBuffers usage, specific to
C++.
#### Prerequisites
This page assumes you have written a FlatBuffers schema and compiled it
with the Schema Compiler. If you have not, please see
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
matter), you've generated a C++ header called `mygame_generated.h` using the
compiler (e.g. `flatc -c mygame.fbs`), you can now start using this in
your program by including the header. As noted, this header relies on
`flatbuffers/flatbuffers.h`, which should be in your include path.
## FlatBuffers C++ library code location
The code for the FlatBuffers C++ library can be found at
`flatbuffers/include/flatbuffers`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/include/flatbuffers).
## Testing the FlatBuffers C++ library
The code to test the C++ library can be found at `flatbuffers/tests`.
The test code itself is located in
[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
This test file is built alongside `flatc`. To review how to build the project,
please read the [Building](@ref flatbuffers_guide_building) documentation.
To run the tests, execute `flattests` from the root `flatbuffers/` directory.
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
run: `./flattests`.
## Using the FlatBuffers C++ library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in C++.*
FlatBuffers supports both reading and writing FlatBuffers in C++.
To use FlatBuffers in your code, first generate the C++ classes from your
schema with the `--cpp` option to `flatc`. Then you can include both FlatBuffers
and the generated code to read or write FlatBuffers.
For example, here is how you would read a FlatBuffer binary file in C++:
First, include the library and generated code. Then read the file into
a `char *` array, which you pass to `GetMonster()`.
```cpp
#include "flatbuffers/flatbuffers.h"
#include "monster_test_generate.h"
#include <iostream> // C++ header file for printing
#include <fstream> // C++ header file for file access
std::ifstream infile;
infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in);
infile.seekg(0,std::ios::end);
int length = infile.tellg();
infile.seekg(0,std::ios::beg);
char *data = new char[length];
infile.read(data, length);
infile.close();
auto monster = GetMonster(data);
```
`monster` is of type `Monster *`, and points to somewhere *inside* your
buffer (root object pointers are not the same as `buffer_pointer` \!).
If you look in your generated header, you'll see it has
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
```cpp
std::cout << "hp : " << monster->hp() << std::endl; // '80'
std::cout << "mana : " << monster->mana() << std::endl; // default value of '150'
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
```
*Note: That we never stored a `mana` value, so it will return the default.*
The following attributes are supported:
- `shared` (on a field): For string fields, this enables the usage of string
pooling (i.e. `CreateSharedString`) as default serialization behavior.
Specifically, `CreateXxxDirect` functions and `Pack` functions for object
based API (see below) will use `CreateSharedString` to create strings.
## Object based API {#flatbuffers_cpp_object_based_api}
FlatBuffers is all about memory efficiency, which is why its base API is written
around using as little as possible of it. This does make the API clumsier
(requiring pre-order construction of all data, and making mutation harder).
For times when efficiency is less important a more convenient object based API
can be used (through `--gen-object-api`) that is able to unpack & pack a
FlatBuffer into objects and standard STL containers, allowing for convenient
construction, access and mutation.
To use:
```cpp
// Autogenerated class from table Monster.
MonsterT monsterobj;
// Deserialize from buffer into object.
GetMonster(flatbuffer)->UnPackTo(&monsterobj);
// Update object directly like a C++ class instance.
cout << monsterobj.name; // This is now a std::string!
monsterobj.name = "Bob"; // Change the name.
// Serialize into new flatbuffer.
FlatBufferBuilder fbb;
fbb.Finish(Monster::Pack(fbb, &monsterobj));
```
The following attributes are specific to the object-based API code generation:
- `native_inline` (on a field): Because FlatBuffer tables and structs are
optionally present in a given buffer, they are best represented as pointers
(specifically std::unique_ptrs) in the native class since they can be null.
This attribute changes the member declaration to use the type directly
rather than wrapped in a unique_ptr.
- `native_default("value")` (on a field): For members that are declared
"native_inline", the value specified with this attribute will be included
verbatim in the class constructor initializer list for this member.
- `native_custom_alloc("custom_allocator")` (on a table or struct): When using the
object-based API all generated NativeTables that are allocated when unpacking
your flatbuffer will use "custom allocator". The allocator is also used by
any std::vector that appears in a table defined with `native_custom_alloc`.
This can be used to provide allocation from a pool for example, for faster
unpacking when using the object-based API.
Minimal Example:
schema:
```cpp
table mytable(native_custom_alloc:"custom_allocator") {
...
}
```
with `custom_allocator` defined before `flatbuffers.h` is included, as:
```cpp
template <typename T> struct custom_allocator : public std::allocator<T> {
typedef T *pointer;
template <class U>
struct rebind {
typedef custom_allocator<U> other;
};
pointer allocate(const std::size_t n) {
return std::allocator<T>::allocate(n);
}
void deallocate(T* ptr, std::size_t n) {
return std::allocator<T>::deallocate(ptr,n);
}
custom_allocator() throw() {}
template <class U>
custom_allocator(const custom_allocator<U>&) throw() {}
};
```
- `native_type("type")` (on a struct): In some cases, a more optimal C++ data
type exists for a given struct. For example, the following schema:
```cpp
struct Vec2 {
x: float;
y: float;
}
```
generates the following Object-Based API class:
```cpp
struct Vec2T : flatbuffers::NativeTable {
float x;
float y;
};
```
However, it can be useful to instead use a user-defined C++ type since it
can provide more functionality, eg.
```cpp
struct vector2 {
float x = 0, y = 0;
vector2 operator+(vector2 rhs) const { ... }
vector2 operator-(vector2 rhs) const { ... }
float length() const { ... }
// etc.
};
```
The `native_type` attribute will replace the usage of the generated class
with the given type. So, continuing with the example, the generated
code would use `vector2` in place of `Vec2T` for all generated code of
the Object-Based API.
However, because the `native_type` is unknown to flatbuffers, the user must
provide the following functions to aide in the serialization process:
```cpp
namespace flatbuffers {
Vec2 Pack(const vector2& obj);
vector2 UnPack(const Vec2& obj);
}
```
- `native_type_pack_name("name")` (on a struct when `native_type` is
specified, too): when you want to use the same `native_type` multiple times
(e. g. with different precision) you must make the names of the Pack/UnPack
functions unique, otherwise you will run into compile errors. This attribute
appends a name to the expected Pack/UnPack functions. So when you
specify `native_type_pack_name("Vec2")` in the above example you now need to
implement these serialization functions instead:
```cpp
namespace flatbuffers {
Vec2 PackVec2(const vector2& obj);
vector2 UnPackVec2(const Vec2& obj);
}
```
Finally, the following top-level attributes:
- `native_include("path")` (at file level): Because the `native_type` attribute
can be used to introduce types that are unknown to flatbuffers, it may be
necessary to include "external" header files in the generated code. This
attribute can be used to directly add an #include directive to the top of
the generated code that includes the specified path directly.
- `force_align`: this attribute may not be respected in the object API,
depending on the aligned of the allocator used with `new`.
# External references
An additional feature of the object API is the ability to allow you to load
multiple independent FlatBuffers, and have them refer to eachothers objects
using hashes which are then represented as typed pointers in the object API.
To make this work have a field in the objects you want to referred to which is
using the string hashing feature (see `hash` attribute in the
[schema](@ref flatbuffers_guide_writing_schema) documentation). Then you have
a similar hash in the field referring to it, along with a `cpp_type`
attribute specifying the C++ type this will refer to (this can be any C++
type, and will get a `*` added).
Then, in JSON or however you create these buffers, make sure they use the
same string (or hash).
When you call `UnPack` (or `Create`), you'll need a function that maps from
hash to the object (see `resolver_function_t` for details).
# Using different pointer types
By default the object tree is built out of `std::unique_ptr`, but you can
influence this either globally (using the `--cpp-ptr-type` argument to
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
pointers. Unlike the smart pointers, naked pointers do not manage memory for
you, so you'll have to manage their lifecycles manually. To reference the
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
# Using different string type
By default the object tree is built out of `std::string`, but you can
influence this either globally (using the `--cpp-str-type` argument to
`flatc`) or per field using the `cpp_str_type` attribute.
The type must support `T::c_str()`, `T::length()` and `T::empty()` as member functions.
Further, the type must be constructible from std::string, as by default a
std::string instance is constructed and then used to initialize the custom
string type. This behavior impedes efficient and zero-copy construction of
custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
so that the custom string type is constructed by passing the pointer and
length of the FlatBuffers String. The custom string class will require a
constructor in the following format: `custom_str_class(const char *, size_t)`.
Please note that the character array is not guaranteed to be NULL terminated,
you should always use the provided size to determine end of string.
## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to
read and write data even if you don't know the exact format of a buffer, and
even allows you to change sizes of strings and vectors in-place.
The way this works is very elegant; there is actually a FlatBuffer schema that
describes schemas (\!) which you can find in `reflection/reflection.fbs`.
The compiler, `flatc`, can write out any schemas it has just parsed as a binary
FlatBuffer, corresponding to this meta-schema.
Loading in one of these binary schemas at runtime allows you traverse any
FlatBuffer data that corresponds to it without knowing the exact format. You
can query what fields are present, and then read/write them after.
For convenient field manipulation, you can include the header
`flatbuffers/reflection.h` which includes both the generated code from the meta
schema, as well as a lot of helper functions.
And example of usage, for the time being, can be found in
`test.cpp/ReflectionTest()`.
## Mini Reflection
A more limited form of reflection is available for direct inclusion in
generated code, which doesn't do any (binary) schema access at all. It was designed
to keep the overhead of reflection as low as possible (on the order of 2-6
bytes per field added to your executable), but doesn't contain all the
information the (binary) schema contains.
You add this information to your generated code by specifying `--reflect-types`
(or instead `--reflect-names` if you also want field / enum names).
You can now use this information, for example to print a FlatBuffer to text:
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
`MonsterTypeTable()` is declared in the generated code for each type. The
string produced is very similar to the JSON produced by the `Parser` based
text generator.
You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
a convenient visitor/iterator so you can write your own output / functionality
based on the mini reflection tables without having to know the FlatBuffers or
reflection encoding.
## Storing maps / dictionaries in a FlatBuffer
FlatBuffers doesn't support maps natively, but there is support to
emulate their behavior with vectors and binary search, which means you
can have fast lookups directly from a FlatBuffer without having to unpack
your data into a `std::map` or similar.
To use it:
- Designate one of the fields in a table as they "key" field. You do this
by setting the `key` attribute on this field, e.g.
`name:string (key)`.
You may only have one key field, and it must be of string or scalar type.
- Write out tables of this type as usual, collect their offsets in an
array or vector.
- Instead of `CreateVector`, call `CreateVectorOfSortedTables`,
which will first sort all offsets such that the tables they refer to
are sorted by the key field, then serialize it.
- Now when you're accessing the FlatBuffer, you can use `Vector::LookupByKey`
instead of just `Vector::Get` to access elements of the vector, e.g.:
`myvector->LookupByKey("Fred")`, which returns a pointer to the
corresponding table type, or `nullptr` if not found.
`LookupByKey` performs a binary search, so should have a similar speed to
`std::map`, though may be faster because of better caching. `LookupByKey`
only works if the vector has been sorted, it will likely not find elements
if it hasn't been sorted.
## Direct memory access
As you can see from the above examples, all elements in a buffer are
accessed through generated accessors. This is because everything is
stored in little endian format on all platforms (the accessor
performs a swap operation on big endian machines), and also because
the layout of things is generally not known to the user.
For structs, layout is deterministic and guaranteed to be the same
across platforms (scalars are aligned to their
own size, and structs themselves to their largest member), and you
are allowed to access this memory directly by using `sizeof()` and
`memcpy` on the pointer to a struct, or even an array of structs.
To compute offsets to sub-elements of a struct, make sure they
are a structs themselves, as then you can use the pointers to
figure out the offset without having to hardcode it. This is
handy for use of arrays of structs with calls like `glVertexAttribPointer`
in OpenGL or similar APIs.
It is important to note is that structs are still little endian on all
machines, so only use tricks like this if you can guarantee you're not
shipping on a big endian machine (an `assert(FLATBUFFERS_LITTLEENDIAN)`
would be wise).
## Access of untrusted buffers
The generated accessor functions access fields over offsets, which is
very quick. These offsets are not verified at run-time, so a malformed
buffer could cause a program to crash by accessing random memory.
When you're processing large amounts of data from a source you know (e.g.
your own generated data on disk), this is acceptable, but when reading
data from the network that can potentially have been modified by an
attacker, this is undesirable.
For this reason, you can optionally use a buffer verifier before you
access the data. This verifier will check all offsets, all sizes of
fields, and null termination of strings to ensure that when a buffer
is accessed, all reads will end up inside the buffer.
Each root type will have a verification function generated for it,
e.g. for `Monster`, you can call:
```cpp
bool ok = VerifyMonsterBuffer(Verifier(buf, len));
```
if `ok` is true, the buffer is safe to read.
Besides untrusted data, this function may be useful to call in debug
mode, as extra insurance against data being corrupted somewhere along
the way.
While verifying a buffer isn't "free", it is typically faster than
a full traversal (since any scalar data is not actually touched),
and since it may cause the buffer to be brought into cache before
reading, the actual overhead may be even lower than expected.
In specialized cases where a denial of service attack is possible,
the verifier has two additional constructor arguments that allow
you to limit the nesting depth and total amount of tables the
verifier may encounter before declaring the buffer malformed. The default is
`Verifier(buf, len, 64 /* max depth */, 1000000, /* max tables */)` which
should be sufficient for most uses.
## Text & schema parsing
Using binary buffers with the generated header provides a super low
overhead use of FlatBuffer data. There are, however, times when you want
to use text formats, for example because it interacts better with source
control, or you want to give your users easy access to data.
Another reason might be that you already have a lot of data in JSON
format, or a tool that generates JSON, and if you can write a schema for
it, this will provide you an easy way to use that data directly.
(see the schema documentation for some specifics on the JSON format
accepted).
Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
There are two ways to use text formats:
#### Using the compiler as a conversion tool
This is the preferred path, as it doesn't require you to add any new
code to your program, and is maximally efficient since you can ship with
binary data. The disadvantage is that it is an extra step for your
users/developers to perform, though you might be able to automate it.
flatc -b myschema.fbs mydata.json
This will generate the binary file `mydata_wire.bin` which can be loaded
as before.
#### Making your program capable of loading text directly
This gives you maximum flexibility. You could even opt to support both,
i.e. check for both files, and regenerate the binary from text when
required, otherwise just load the binary.
This option is currently only available for C++, or Java through JNI.
As mentioned in the section "Building" above, this technique requires
you to link a few more files into your program, and you'll want to include
`flatbuffers/idl.h`.
Load text (either a schema or json) into an in-memory buffer (there is a
convenient `LoadFile()` utility function in `flatbuffers/util.h` if you
wish). Construct a parser:
```cpp
flatbuffers::Parser parser;
```
Now you can parse any number of text files in sequence:
```cpp
parser.Parse(text_file.c_str());
```
This works similarly to how the command-line compiler works: a sequence
of files parsed by the same `Parser` object allow later files to
reference definitions in earlier files. Typically this means you first
load a schema file (which populates `Parser` with definitions), followed
by one or more JSON files.
As optional argument to `Parse`, you may specify a null-terminated list of
include paths. If not specified, any include statements try to resolve from
the current directory.
If there were any parsing errors, `Parse` will return `false`, and
`Parser::error_` contains a human readable error string with a line number
etc, which you should present to the creator of that file.
After each JSON file, the `Parser::fbb` member variable is the
`FlatBufferBuilder` that contains the binary buffer version of that
file, that you can access as described above.
`samples/sample_text.cpp` is a code sample showing the above operations.
## Threading
Reading a FlatBuffer does not touch any memory outside the original buffer,
and is entirely read-only (all const), so is safe to access from multiple
threads even without synchronisation primitives.
Creating a FlatBuffer is not thread safe. All state related to building
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
outside of it is touched. To make this thread safe, either do not
share instances of FlatBufferBuilder between threads (recommended), or
manually wrap it in synchronisation primitives. There's no automatic way to
accomplish this, by design, as we feel multithreaded construction
of a single buffer will be rare, and synchronisation overhead would be costly.
## Advanced union features
The C++ implementation currently supports vectors of unions (i.e. you can
declare a field as `[T]` where `T` is a union type instead of a table type). It
also supports structs and strings in unions, besides tables.
For an example of these features, see `tests/union_vector`, and
`UnionVectorTest` in `test.cpp`.
Since these features haven't been ported to other languages yet, if you
choose to use them, you won't be able to use these buffers in other languages
(`flatc` will refuse to compile a schema that uses these features).
These features reduce the amount of "table wrapping" that was previously
needed to use unions.
To use scalars, simply wrap them in a struct.
## Depth limit of nested objects and stack-overflow control
The parser of Flatbuffers schema or json-files is kind of recursive parser.
To avoid stack-overflow problem the parser has a built-in limiter of
recursion depth. Number of nested declarations in a schema or number of
nested json-objects is limited. By default, this depth limit set to `64`.
It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH`
definition. This definition can be helpful for testing purposes or embedded
applications. For details see [build](@ref flatbuffers_guide_building) of
CMake-based projects.
## Dependence from C-locale {#flatbuffers_locale_cpp}
The Flatbuffers [grammar](@ref flatbuffers grammar) uses ASCII
character set for identifiers, alphanumeric literals, reserved words.
Internal implementation of the Flatbuffers depends from functions which
depend from C-locale: `strtod()` or `strtof()`, for example.
The library expects the dot `.` symbol as the separator of an integer
part from the fractional part of a float number.
Another separator symbols (`,` for example) will break the compatibility
and may lead to an error while parsing a Flatbuffers schema or a json file.
The Standard C locale is a global resource, there is only one locale for
the entire application. Some modern compilers and platforms have
locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
`strtoll_l`, `strtoull_l` to resolve this dependency.
These functions use specified locale rather than the global or per-thread
locale instead. They are part of POSIX-2008 but not part of the C/C++
standard library, therefore, may be missing on some platforms.
The Flatbuffers library try to detect these functions at configuration and
compile time:
- CMake `"CMakeLists.txt"`:
- Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
- Compile-time `"/include/base.h"`:
- `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
- `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
set to `0` or `1`.
To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
To test the compatibility of the Flatbuffers library with
a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
```sh
>FLATBUFFERS_TEST_LOCALE="" ./flattests
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
```
## Support of floating-point numbers
The Flatbuffers library assumes that a C++ compiler and a CPU are
compatible with the `IEEE-754` floating-point standard.
The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
### Support of hexadecimal and special floating-point numbers
According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
literals. The Flatbuffers library has a code to detect a compiler compatibility
with the literals. If necessary conditions are met the preprocessor constant
`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
The support of floating-point literals will be limited at compile time
if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
In this case, schemas with hexadecimal or special literals cannot be used.
### Comparison of floating-point NaN values
The floating-point `NaN` (`not a number`) is special value which
representing an undefined or unrepresentable value.
`NaN` may be explicitly assigned to variables, typically as a representation
for missing values or may be a result of a mathematical operation.
The `IEEE-754` defines two kind of `NaNs`:
- Quiet NaNs, or `qNaNs`.
- Signaling NaNs, or `sNaNs`.
According to the `IEEE-754`, a comparison with `NaN` always returns
an unordered result even when compared with itself. As a result, a whole
Flatbuffers object will be not equal to itself if has one or more `NaN`.
Flatbuffers scalar fields that have the default value are not actually stored
in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
Scalar fields with `NaN` defaults break this behavior.
If a schema has a lot of `NaN` defaults the Flatbuffers can override
the unordered comparison by the ordered: `(NaN==NaN)->true`.
This ordered comparison is enabled when compiling a program with the symbol
`FLATBUFFERS_NAN_DEFAULTS` defined.
Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
if GCC or Clang used. These compilers have a compile-time implementation
of `isnan` checking which MSVC does not.
<br>

View File

@@ -1,265 +0,0 @@
Use in C# {#flatbuffers_guide_use_c-sharp}
==============
## Before you get started
Before diving into the FlatBuffers usage in C#, 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 C#).
This page is designed to cover the nuances of FlatBuffers usage,
specific to C#.
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 C# code location
The code for the FlatBuffers C# library can be found at
`flatbuffers/net/FlatBuffers`. You can browse the library on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
FlatBuffers).
## Building the FlatBuffers C# library
The `FlatBuffers.csproj` project contains multitargeting for .NET Standard 2.1,
.NET 6 and .NET 8.
You can build for a specific framework target when using the cross-platform
[.NET Core SDK](https://dotnet.microsoft.com/download) by adding the `-f`
command line option:
~~~{.sh}
dotnet build -f netstandard2.1 "FlatBuffers.csproj"
~~~
The `FlatBuffers.csproj` project also provides support for defining various
conditional compilation symbols (see "Conditional compilation symbols" section
below) using the `-p` command line option:
~~~{.sh}
dotnet build -f netstandard2.1 -p:ENABLE_SPAN_T=true -p:UNSAFE_BYTEBUFFER=true "FlatBuffers.csproj"
~~~
## Testing the FlatBuffers C# library
The code to test the libraries can be found at `flatbuffers/tests`.
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
https://www.visualstudio.com), and compile/run the project.
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
Once you have installed Mono, you can run the tests from the command line
by running the following commands from inside the `FlatBuffers.Test` folder:
~~~{.sh}
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
mono Assert.exe
~~~
## Using the FlatBuffers C# library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in C#.*
FlatBuffers supports reading and writing binary FlatBuffers in C#.
To use FlatBuffers in your own code, first generate C# classes from your
schema with the `--csharp` 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 C#:
First, import the library and generated code. Then, you read a FlatBuffer binary
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
pass to the `GetRootAsMyRootType` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
using MyGame.Example;
using Google.FlatBuffers;
// This snippet ignores exceptions for brevity.
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
ByteBuffer bb = new ByteBuffer(data);
Monster monster = Monster.GetRootAsMonster(bb);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access the data from the `Monster monster`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
short hp = monster.Hp;
Vec3 pos = monster.Pos;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C# code naming follows standard C# style with PascalCasing identifiers,
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
available as properties instead of parameterless accessor methods.
The performance-enhancing methods to which you can pass an already created
object are prefixed with `Get`, e.g.:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
// property
var pos = monster.Pos;
// method filling a preconstructed object
var preconstructedPos = new Vec3();
monster.GetPos(preconstructedPos);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Storing dictionaries in a FlatBuffer
FlatBuffers doesn't support dictionaries natively, but there is support to
emulate their behavior with vectors and binary search, which means you
can have fast lookups directly from a FlatBuffer without having to unpack
your data into a `Dictionary` or similar.
To use it:
- Designate one of the fields in a table as the "key" field. You do this
by setting the `key` attribute on this field, e.g.
`name:string (key)`.
You may only have one key field, and it must be of string or scalar type.
- Write out tables of this type as usual, collect their offsets in an
array.
- Instead of calling standard generated method,
e.g.: `Monster.createTestarrayoftablesVector`,
call `CreateSortedVectorOfMonster` in C#
which will first sort all offsets such that the tables they refer to
are sorted by the key field, then serialize it.
- Now when you're accessing the FlatBuffer, you can use
the `ByKey` accessor to access elements of the vector, e.g.:
`monster.TestarrayoftablesByKey("Frodo")` in C#,
which returns an object of the corresponding table type,
or `null` if not found.
`ByKey` performs a binary search, so should have a similar
speed to `Dictionary`, though may be faster because of better caching.
`ByKey` only works if the vector has been sorted, it will
likely not find elements if it hasn't been sorted.
## Buffer verification
As mentioned in [C++ Usage](@ref flatbuffers_guide_use_cpp) buffer
accessor functions do not verify buffer offsets at run-time.
If it is necessary, you can optionally use a buffer verifier before you
access the data. This verifier will check all offsets, all sizes of
fields, and null termination of strings to ensure that when a buffer
is accessed, all reads will end up inside the buffer.
Each root type will have a verification function generated for it,
e.g. `Monster.VerifyMonster`. This can be called as shown:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
var ok = Monster.VerifyMonster(buf);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if `ok` is true, the buffer is safe to read.
For a more detailed control of verification `MonsterVerify.Verify`
for `Monster` type can be used:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
# Sequence of calls
FlatBuffers.Verifier verifier = new FlatBuffers.Verifier(buf);
var ok = verifier.VerifyBuffer("MONS", false, MonsterVerify.Verify);
# Or single line call
var ok = new FlatBuffers.Verifier(bb).setStringCheck(true).\
VerifyBuffer("MONS", false, MonsterVerify.Verify);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if `ok` is true, the buffer is safe to read.
A second parameter of `verifyBuffer` specifies whether buffer content is
size prefixed or not. In the example above, the buffer is assumed to not include
size prefix (`false`).
Verifier supports options that can be set using appropriate fluent methods:
* SetMaxDepth - limit the nesting depth. Default: 1000000
* SetMaxTables - total amount of tables the verifier may encounter. Default: 64
* SetAlignmentCheck - check content alignment. Default: True
* SetStringCheck - check if strings contain termination '0' character. Default: true
## Text parsing
There currently is no support for parsing text (Schema's and JSON) directly
from C#, though you could use the C++ parser through native call
interfaces available to each language. Please see the
C++ documentation for more on text parsing.
## Object based API
FlatBuffers is all about memory efficiency, which is why its base API is written
around using as little as possible of it. This does make the API clumsier
(requiring pre-order construction of all data, and making mutation harder).
For times when efficiency is less important a more convenient object based API
can be used (through `--gen-object-api`) that is able to unpack & pack a
FlatBuffer into objects and standard `System.Collections.Generic` containers,
allowing for convenient construction, access and mutation.
To use:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
// Deserialize from buffer into object.
MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
// Update object directly like a C# class instance.
Console.WriteLine(monsterobj.Name);
monsterobj.Name = "Bob"; // Change the name.
// Serialize into new flatbuffer.
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Json Serialization
An additional feature of the object API is the ability to allow you to
serialize & deserialize a JSON text.
To use Json Serialization, add `--cs-gen-json-serializer` option to `flatc` and
add `Newtonsoft.Json` nuget package to csproj. This requires explicitly setting
the `--gen-object-api` option as well.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
// Deserialize MonsterT from json
string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
// Serialize MonsterT to json
string jsonText2 = mon.SerializeToJson();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Limitation
* `hash` attribute currently not supported.
* NuGet package Dependency
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
## Conditional compilation symbols
There are three conditional compilation symbols that have an impact on
performance/features of the C# `ByteBuffer` implementation.
* `UNSAFE_BYTEBUFFER`
This will use unsafe code to manipulate the underlying byte array. This can
yield a reasonable performance increase.
* `BYTEBUFFER_NO_BOUNDS_CHECK`
This will disable the bounds check asserts to the byte array. This can yield a
small performance gain in normal code.
* `ENABLE_SPAN_T`
This will enable reading and writing blocks of memory with a `Span<T>` instead
of just `T[]`. You can also enable writing directly to shared memory or other
types of memory by providing a custom implementation of `ByteBufferAllocator`.
`ENABLE_SPAN_T` also requires `UNSAFE_BYTEBUFFER` to be defined, or .NET
Standard 2.1.
Using `UNSAFE_BYTEBUFFER` and `BYTEBUFFER_NO_BOUNDS_CHECK` together can yield a
performance gain of ~15% for some operations, however doing so is potentially
dangerous. Do so at your own risk!
<br>

View File

@@ -1,131 +0,0 @@
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 Dart 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).
## Object based API
FlatBuffers is all about memory efficiency, which is why its base API is written
around using as little as possible of it. This does make the API clumsier
(requiring pre-order construction of all data, and making mutation harder).
For times when efficiency is less important a more convenient object based API
can be used (through `--gen-object-api`) that is able to unpack & pack a FlatBuffer
into objects and lists, allowing for convenient construction, access and mutation.
To use:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
// Deserialize from buffer into object.
MonsterT monster = Monster(flatbuffer).unpack();
// Update object directly like a Dart class instance.
print(monster.Name);
monster.Name = "Bob"; // Change the name.
// Serialize into new flatbuffer.
final fbb = Builder();
fbb.Finish(monster.pack(fbb));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -1,188 +0,0 @@
FlatBuffers {#flatbuffers_index}
===========
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
It was originally created at Google for game development and other
performance-critical applications.
It is available as Open Source on [GitHub](http://github.com/google/flatbuffers)
under the Apache license, v2 (see LICENSE).
## Why use FlatBuffers?
- **Access to serialized data without parsing/unpacking** - What sets
FlatBuffers apart is that it represents hierarchical data in a flat
binary buffer in such a way that it can still be accessed directly
without parsing/unpacking, while also still supporting data
structure evolution (forwards/backwards compatibility).
- **Memory efficiency and speed** - The only memory needed to access
your data is that of the buffer. It requires 0 additional allocations
(in C++, other languages may vary). FlatBuffers is also very
suitable for use with mmap (or streaming), requiring only part of the
buffer to be in memory. Access is close to the speed of raw
struct access with only one extra indirection (a kind of vtable) to
allow for format evolution and optional fields. It is aimed at
projects where spending time and space (many memory allocations) to
be able to access or construct serialized data is undesirable, such
as in games or any other performance sensitive applications. See the
[benchmarks](@ref flatbuffers_benchmarks) for details.
- **Flexible** - Optional fields means not only do you get great
forwards and backwards compatibility (increasingly important for
long-lived games: don't have to update all data with each new
version!). It also means you have a lot of choice in what data you
write and what data you don't, and how you design data structures.
- **Tiny code footprint** - Small amounts of generated code, and just
a single small header as the minimum dependency, which is very easy
to integrate. Again, see the benchmark section for details.
- **Strongly typed** - Errors happen at compile time rather than
manually having to write repetitive and error prone run-time checks.
Useful code can be generated for you.
- **Convenient to use** - Generated C++ code allows for terse access
& construction code. Then there's optional functionality for parsing
schemas and JSON-like text representations at runtime efficiently if
needed (faster and more memory efficient than other JSON
parsers).
Java, Kotlin and Go code supports object-reuse. C# has efficient struct based
accessors.
- **Cross platform code with no dependencies** - C++ code will work
with any recent gcc/clang and VS2010. Comes with build files for the tests &
samples (Android .mk files, and cmake for all other platforms).
### Why not use Protocol Buffers, or .. ?
Protocol Buffers is indeed relatively similar to FlatBuffers,
with the primary difference being that FlatBuffers does not need a parsing/
unpacking step to a secondary representation before you can
access data, often coupled with per-object memory allocation. The code
is an order of magnitude bigger, too. Protocol Buffers has no optional
text import/export.
### But all the cool kids use JSON!
JSON is very readable (which is why we use it as our optional text
format) and very convenient when used together with dynamically typed
languages (such as JavaScript). When serializing data from statically
typed languages, however, JSON not only has the obvious drawback of runtime
inefficiency, but also forces you to write *more* code to access data
(counterintuitively) due to its dynamic-typing serialization system.
In this context, it is only a better choice for systems that have very
little to no information ahead of time about what data needs to be stored.
If you do need to store data that doesn't fit a schema, FlatBuffers also
offers a schema-less (self-describing) version!
Read more about the "why" of FlatBuffers in the
[white paper](@ref flatbuffers_white_paper).
### Who uses FlatBuffers?
- [Cocos2d-x](http://www.cocos2d-x.org/), the #1 open source mobile game
engine, uses it to serialize all their
[game data](http://www.cocos2d-x.org/reference/native-cpp/V3.5/d7/d2d/namespaceflatbuffers.html).
- [Facebook](http://facebook.com/) uses it for client-server communication in
their Android app. They have a nice
[article](https://code.facebook.com/posts/872547912839369/improving-facebook-s-performance-on-android-with-flatbuffers/)
explaining how it speeds up loading their posts.
- [Fun Propulsion Labs](https://developers.google.com/games/#Tools)
at Google uses it extensively in all their libraries and games.
## Usage in brief
This section is a quick rundown of how to use this system. Subsequent
sections provide a more in-depth usage guide.
- Write a schema file that allows you to define the data structures
you may want to serialize. Fields can have a scalar type
(ints/floats of all sizes), or they can be a: string; array of any type;
reference to yet another object; or, a set of possible objects (unions).
Fields are optional and have defaults, so they don't need to be
present for every object instance.
- Use `flatc` (the FlatBuffer compiler) to generate a C++ header (or
Java/Kotlin/C#/Go/Python.. classes) with helper classes to access and construct
serialized data. This header (say `mydata_generated.h`) only depends on
`flatbuffers.h`, which defines the core functionality.
- Use the `FlatBufferBuilder` class to construct a flat binary buffer.
The generated functions allow you to add objects to this
buffer recursively, often as simply as making a single function call.
- Store or send your buffer somewhere!
- When reading it back, you can obtain the pointer to the root object
from the binary buffer, and from there traverse it conveniently
in-place with `object->field()`.
## In-depth documentation
- How to [build the compiler](@ref flatbuffers_guide_building) and samples on
various platforms.
- How to [use the compiler](@ref flatbuffers_guide_using_schema_compiler).
- How to [write a schema](@ref flatbuffers_guide_writing_schema).
- How to [use the generated C++ code](@ref flatbuffers_guide_use_cpp) in your
own programs.
- How to [use the generated Java code](@ref flatbuffers_guide_use_java)
in your own programs.
- How to [use the generated C# code](@ref flatbuffers_guide_use_c-sharp)
in your own programs.
- How to [use the generated Kotlin code](@ref flatbuffers_guide_use_kotlin)
in your own programs.
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
own programs.
- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
own programs.
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
own programs.
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
own programs.
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
own programs.
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
own programs.
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
own programs.
- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
own programs.
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
using FlatBuffers.
- A [white paper](@ref flatbuffers_white_paper) explaining the "why" of
FlatBuffers.
- How to use the [schema-less](@ref flexbuffers) version of
FlatBuffers.
- A description of the [internals](@ref flatbuffers_internals) of FlatBuffers.
- A formal [grammar](@ref flatbuffers_grammar) of the schema language.
## Online resources
- [GitHub repository](http://github.com/google/flatbuffers)
- [Landing page](http://google.github.io/flatbuffers)
- [FlatBuffers Google Group](https://groups.google.com/forum/#!forum/flatbuffers)
- [Discord](https://discord.gg/6qgKs3R) and [Gitter](https://gitter.im/lobster_programming_language/community) chat.
- [FlatBuffers Issues Tracker](http://github.com/google/flatbuffers/issues)
- Independent implementations & tools:
- [FlatCC](https://github.com/dvidelabs/flatcc) Alternative FlatBuffers
parser, code generator and runtime all in C.
- Videos:
- Colt's [DevByte](https://www.youtube.com/watch?v=iQTxMkSJ1dQ).
- GDC 2015 [Lightning Talk](https://www.youtube.com/watch?v=olmL1fUnQAQ).
- FlatBuffers for [Go](https://www.youtube.com/watch?v=-BPVId_lA5w).
- Evolution of FlatBuffers
[visualization](https://www.youtube.com/watch?v=a0QE0xS8rKM).
- Useful documentation created by others:
- [FlatBuffers in Go](https://rwinslow.com/tags/flatbuffers/)
- [FlatBuffers in Android](http://frogermcs.github.io/flatbuffers-in-android-introdution/)
- [Parsing JSON to FlatBuffers in Java](http://frogermcs.github.io/json-parsing-with-flatbuffers-in-android/)
- [FlatBuffers in Unity](http://exiin.com/blog/flatbuffers-for-unity-sample-code/)
- [FlexBuffers C#](https://github.com/mzaks/FlexBuffers-CSharp) and
[article](https://medium.com/@icex33/flexbuffers-for-unity3d-4d1ab5c53fbe?)
on its use.

View File

@@ -1,204 +0,0 @@
FlexBuffers {#flexbuffers}
==========
FlatBuffers was designed around schemas, because when you want maximum
performance and data consistency, strong typing is helpful.
There are however times when you want to store data that doesn't fit a
schema, because you can't know ahead of time what all needs to be stored.
For this, FlatBuffers has a dedicated format, called FlexBuffers.
This is a binary format that can be used in conjunction
with FlatBuffers (by storing a part of a buffer in FlexBuffers
format), or also as its own independent serialization format.
While it loses the strong typing, you retain the most unique advantage
FlatBuffers has over other serialization formats (schema-based or not):
FlexBuffers can also be accessed without parsing / copying / object allocation.
This is a huge win in efficiency / memory friendly-ness, and allows unique
use cases such as mmap-ing large amounts of free-form data.
FlexBuffers' design and implementation allows for a very compact encoding,
combining automatic pooling of strings with automatic sizing of containers to
their smallest possible representation (8/16/32/64 bits). Many values and
offsets can be encoded in just 8 bits. While a schema-less representation is
usually more bulky because of the need to be self-descriptive, FlexBuffers
generates smaller binaries for many cases than regular FlatBuffers.
FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
only use it if you need it.
# Usage in C++
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
and `util.h`.
To create a buffer:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
flexbuffers::Builder fbb;
fbb.Int(13);
fbb.Finish();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You create any value, followed by `Finish`. Unlike FlatBuffers which requires
the root value to be a table, here any value can be the root, including a lonely
int value.
You can now access the `std::vector<uint8_t>` that contains the encoded value
as `fbb.GetBuffer()`. Write it, send it, or store it in a parent FlatBuffer. In
this case, the buffer is just 3 bytes in size.
To read this value back, you could just say:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto root = flexbuffers::GetRoot(my_buffer);
int64_t i = root.AsInt64();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FlexBuffers stores ints only as big as needed, so it doesn't differentiate
between different sizes of ints. You can ask for the 64 bit version,
regardless of what you put in. In fact, since you demand to read the root
as an int, if you supply a buffer that actually contains a float, or a
string with numbers in it, it will convert it for you on the fly as well,
or return 0 if it can't. If instead you actually want to know what is inside
the buffer before you access it, you can call `root.GetType()` or `root.IsInt()`
etc.
Here's a slightly more complex value you could write instead of `fbb.Int` above:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
fbb.Map([&]() {
fbb.Vector("vec", [&]() {
fbb.Int(-100);
fbb.String("Fred");
fbb.IndirectFloat(4.0f);
});
fbb.UInt("foo", 100);
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This stores the equivalent of the JSON value
`{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`. The root is a dictionary that has
just two key-value pairs, with keys `vec` and `foo`. Unlike FlatBuffers, it
actually has to store these keys in the buffer (which it does only once if
you store multiple such objects, by pooling key values), but also unlike
FlatBuffers it has no restriction on the keys (fields) that you use.
The map constructor uses a C++11 Lambda to group its children, but you can
also use more conventional start/end calls if you prefer.
The first value in the map is a vector. You'll notice that unlike FlatBuffers,
you can use mixed types. There is also a `TypedVector` variant that only
allows a single type, and uses a bit less memory.
`IndirectFloat` is an interesting feature that allows you to store values
by offset rather than inline. Though that doesn't make any visible change
to the user, the consequence is that large values (especially doubles or
64 bit ints) that occur more than once can be shared (see ReuseValue).
Another use case is inside of vectors, where the largest element makes
up the size of all elements (e.g. a single double forces all elements to
64bit), so storing a lot of small integers together with a double is more efficient if the double is indirect.
Accessing it:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto map = flexbuffers::GetRoot(my_buffer).AsMap();
map.size(); // 2
auto vec = map["vec"].AsVector();
vec.size(); // 3
vec[0].AsInt64(); // -100;
vec[1].AsString().c_str(); // "Fred";
vec[1].AsInt64(); // 0 (Number parsing failed).
vec[2].AsDouble(); // 4.0
vec[2].AsString().IsTheEmptyString(); // true (Wrong Type).
vec[2].AsString().c_str(); // "" (This still works though).
vec[2].ToString().c_str(); // "4" (Or have it converted).
map["foo"].AsUInt8(); // 100
map["unknown"].IsNull(); // true
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Usage in Java
Java implementation follows the C++ one, closely.
For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`,
one could use the following code:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
int smap = builder.startMap();
int svec = builder.startVector();
builder.putInt(-100);
builder.putString("Fred");
builder.putFloat(4.0);
builder.endVector("vec", svec, false, false);
builder.putInt("foo", 100);
builder.endMap(null, smap);
ByteBuffer bb = builder.finish();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similarly, to read the data, just:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap();
map.size(); // 2
FlexBuffers.Vector vec = map.get("vec").asVector();
vec.size(); // 3
vec.get(0).asLong(); // -100;
vec.get(1).asString(); // "Fred";
vec.get(1).asLong(); // 0 (Number parsing failed).
vec.get(2).asFloat(); // 4.0
vec.get(2).asString().isEmpty(); // true (Wrong Type).
vec.get(2).asString(); // "" (This still works though).
vec.get(2).toString(); // "4.0" (Or have it converted).
map.get("foo").asUInt(); // 100
map.get("unknown").isNull(); // true
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Binary encoding
A description of how FlexBuffers are encoded is in the
[internals](@ref flatbuffers_internals) document.
# Nesting inside a FlatBuffer
You can mark a field as containing a FlexBuffer, e.g.
a:[ubyte] (flexbuffer);
A special accessor will be generated that allows you to access the root value
directly, e.g. `a_flexbuffer_root().AsInt64()`.
# Efficiency tips
* Vectors generally are a lot more efficient than maps, so prefer them over maps
when possible for small objects. Instead of a map with keys `x`, `y` and `z`,
use a vector. Better yet, use a typed vector. Or even better, use a fixed
size typed vector.
* Maps are backwards compatible with vectors, and can be iterated as such.
You can iterate either just the values (`map.Values()`), or in parallel with
the keys vector (`map.Keys()`). If you intend
to access most or all elements, this is faster than looking up each element
by key, since that involves a binary search of the key vector.
* When possible, don't mix values that require a big bit width (such as double)
in a large vector of smaller values, since all elements will take on this
width. Use `IndirectDouble` when this is a possibility. Note that
integers automatically use the smallest width possible, i.e. if you ask
to serialize an int64_t whose value is actually small, you will use less
bits. Doubles are represented as floats whenever possible losslessly, but
this is only possible for few values.
Since nested vectors/maps are stored over offsets, they typically don't
affect the vector width.
* To store large arrays of byte data, use a blob. If you'd use a typed
vector, the bit width of the size field may make it use more space than
expected, and may not be compatible with `memcpy`.
Similarly, large arrays of (u)int16_t may be better off stored as a
binary blob if their size could exceed 64k elements.
Construction and use are otherwise similar to strings.

View File

@@ -1,26 +0,0 @@
Go API
======
\addtogroup flatbuffers_go_api
<!-- Note: The `GoApi_generate.txt` code snippet was generated using `godoc` and
customized for use with this markdown file. To regenerate the file, use the
`godoc` tool (http://godoc.org) with the files in the `flatbuffers/go`
folder.
You may need to ensure that copies of the files exist in the `src/`
subfolder at the path set by the `$GOROOT` environment variable. You can
either move the files to `$GOROOT/src/flatbuffers` manually, if `$GOROOT`
is already set, otherwise you will need to manually set the `$GOROOT`
variable to a path and create `src/flatbuffers` subfolders at that path.
Then copy the flatbuffers files into `$GOROOT/src/flatbuffers`. (Some
versions of `godoc` include a `-path` flag. This could be used instead, if
available).
Once the files exist at the `$GOROOT/src/flatbuffers` location, you can
regenerate this doc using the following command:
`godoc flatbuffers > GoApi_generated.txt`.
After the documentation is generated, you will have to manually remove any
non-user facing documentation from this file. -->
\snippet GoApi_generated.txt Go API

View File

@@ -1,125 +0,0 @@
// This file was generated using `godoc` and customized for use with the
// API Reference documentation. To recreate this file, use the `godoc` tool
// (http://godoc.org) with the files in the `flatbuffers/go` folder.
//
// Note: You may need to ensure that copies of the files exist in the
// `src/` subfolder at the path set by the `$GOROOT` environment variable.
// You can either move the files to `$GOROOT/src/flatbuffers` manually, if
// `$GOROOT` is already set, otherwise you will need to manually set the
// `$GOROOT` variable to a path and create `src/flatbuffers` subfolders at that
// path. Then copy these files into `$GOROOT/src/flatbuffers`. (Some versions of
// `godoc` include a `-path` flag. This could be used instead, if available).
//
// Once the files exist at the `$GOROOT/src/flatbuffers` location, you can
// regenerate this doc using the following command:
// `godoc flatbuffers > GoApi_generated.txt`.
//
// After the documentation is generated, you will have to manually remove any
// non-user facing documentation from this file.
/// [Go API]
PACKAGE DOCUMENTATION
package flatbuffers
Package flatbuffers provides facilities to read and write flatbuffers
objects.
TYPES
type Builder struct {
// `Bytes` gives raw access to the buffer. Most users will want to use
// FinishedBytes() instead.
Bytes []byte
}
Builder is a state machine for creating FlatBuffer objects. Use a
Builder to construct object(s) starting from leaf nodes.
A Builder constructs byte buffers in a last-first manner for simplicity
and performance.
FUNCTIONS
func NewBuilder(initialSize int) *Builder
NewBuilder initializes a Builder of size `initial_size`. The internal
buffer is grown as needed.
func (b *Builder) CreateByteString(s []byte) UOffsetT
CreateByteString writes a byte slice as a string (null-terminated).
func (b *Builder) CreateByteVector(v []byte) UOffsetT
CreateByteVector writes a ubyte vector
func (b *Builder) CreateString(s string) UOffsetT
CreateString writes a null-terminated string as a vector.
func (b *Builder) EndVector(vectorNumElems int) UOffsetT
EndVector writes data necessary to finish vector construction.
func (b *Builder) Finish(rootTable UOffsetT)
Finish finalizes a buffer, pointing to the given `rootTable`.
func (b *Builder) FinishedBytes() []byte
FinishedBytes returns a pointer to the written data in the byte buffer.
Panics if the builder is not in a finished state (which is caused by
calling `Finish()`).
func (b *Builder) Head() UOffsetT
Head gives the start of useful data in the underlying byte buffer. Note:
unlike other functions, this value is interpreted as from the left.
func (b *Builder) PrependBool(x bool)
PrependBool prepends a bool to the Builder buffer. Aligns and checks for
space.
func (b *Builder) PrependByte(x byte)
PrependByte prepends a byte to the Builder buffer. Aligns and checks for
space.
func (b *Builder) PrependFloat32(x float32)
PrependFloat32 prepends a float32 to the Builder buffer. Aligns and
checks for space.
func (b *Builder) PrependFloat64(x float64)
PrependFloat64 prepends a float64 to the Builder buffer. Aligns and
checks for space.
func (b *Builder) PrependInt16(x int16)
PrependInt16 prepends a int16 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependInt32(x int32)
PrependInt32 prepends a int32 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependInt64(x int64)
PrependInt64 prepends a int64 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependInt8(x int8)
PrependInt8 prepends a int8 to the Builder buffer. Aligns and checks for
space.
func (b *Builder) PrependUOffsetT(off UOffsetT)
PrependUOffsetT prepends an UOffsetT, relative to where it will be
written.
func (b *Builder) PrependUint16(x uint16)
PrependUint16 prepends a uint16 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependUint32(x uint32)
PrependUint32 prepends a uint32 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependUint64(x uint64)
PrependUint64 prepends a uint64 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) PrependUint8(x uint8)
PrependUint8 prepends a uint8 to the Builder buffer. Aligns and checks
for space.
func (b *Builder) Reset()
Reset truncates the underlying Builder buffer, facilitating alloc-free
reuse of a Builder. It also resets bookkeeping data.
/// [Go API]

View File

@@ -1,99 +0,0 @@
Use in Go {#flatbuffers_guide_use_go}
=========
## Before you get started
Before diving into the FlatBuffers usage in Go, 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 Go).
This page is designed to cover the nuances of FlatBuffers usage, specific to
Go.
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 Go library code location
The code for the FlatBuffers Go library can be found at
`flatbuffers/go`. You can browse the library code on the [FlatBuffers
GitHub page](https://github.com/google/flatbuffers/tree/master/go).
## Testing the FlatBuffers Go library
The code to test the Go library can be found at `flatbuffers/tests`.
The test code itself is located in [go_test.go](https://github.com/google/
flatbuffers/blob/master/tests/go_test.go).
To run the tests, use the [GoTest.sh](https://github.com/google/flatbuffers/
blob/master/tests/GoTest.sh) shell script.
*Note: The shell script requires [Go](https://golang.org/doc/install) to
be installed.*
## Using the FlatBuffers Go library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Go.*
FlatBuffers supports reading and writing binary FlatBuffers in Go.
To use FlatBuffers in your own code, first generate Go classes from your
schema with the `--go` 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 Go: First,
include the library and generated code. Then read a FlatBuffer binary file into
a `[]byte`, which you pass to the `GetRootAsMonster` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
import (
example "MyGame/Example"
flatbuffers "github.com/google/flatbuffers/go"
"os"
)
buf, err := os.ReadFile("monster.dat")
// handle err
monster := example.GetRootAsMonster(buf, 0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
hp := monster.Hp()
pos := monster.Pos(nil)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
monster := example.GetRootAsMonster(buf, 0)
// Set table field.
if ok := monster.MutateHp(10); !ok {
panic("failed to mutate Hp")
}
// Set struct field.
monster.Pos().MutateZ(4)
// This mutation will fail because the mana field is not available in
// the buffer. It should be set when creating the buffer.
if ok := monster.MutateMana(20); !ok {
panic("failed to mutate Hp")
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly
from Go, though you could use the C++ parser through cgo. Please see the
C++ documentation for more on text parsing.
<br>

View File

@@ -1,74 +0,0 @@
Grammar of the schema language {#flatbuffers_grammar}
==============================
schema = include*
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
file_extension_decl | file_identifier_decl |
attribute\_decl | rpc\_decl | object )*
include = `include` string\_constant `;`
namespace\_decl = `namespace` ident ( `.` ident )* `;`
attribute\_decl = `attribute` ident | `"` ident `"` `;`
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
enum\_decl = ( `enum` ident `:` type | `union` ident ) metadata `{`
commasep( enumval\_decl ) `}`
root\_decl = `root_type` ident `;`
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
rpc\_decl = `rpc_service` ident `{` rpc\_method+ `}`
rpc\_method = ident `(` ident `)` `:` ident metadata `;`
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
`float` | `long` | `ulong` | `double` |
`int8` | `uint8` | `int16` | `uint16` | `int32` | `uint32`| `int64` | `uint64` |
`float32` | `float64` |
`string` | `[` type `]` | ident
enumval\_decl = ident [ `=` integer\_constant ] metadata
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
scalar = boolean\_constant | integer\_constant | float\_constant
object = `{` commasep( ident `:` value ) `}`
single\_value = scalar | string\_constant
value = single\_value | object | `[` commasep( value ) `]`
commasep(x) = [ x ( `,` x )\* ]
file_extension_decl = `file_extension` string\_constant `;`
file_identifier_decl = `file_identifier` string\_constant `;`
string\_constant = `\".*?\"`
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
`[:digit:]` = `[0-9]`
`[:xdigit:]` = `[0-9a-fA-F]`
dec\_integer\_constant = `[-+]?[:digit:]+`
hex\_integer\_constant = `[-+]?0[xX][:xdigit:]+`
integer\_constant = dec\_integer\_constant | hex\_integer\_constant
dec\_float\_constant = `[-+]?(([.][:digit:]+)|([:digit:]+[.][:digit:]*)|([:digit:]+))([eE][-+]?[:digit:]+)?`
hex\_float\_constant = `[-+]?0[xX](([.][:xdigit:]+)|([:xdigit:]+[.][:xdigit:]*)|([:xdigit:]+))([pP][-+]?[:digit:]+)`
special\_float\_constant = `[-+]?(nan|inf|infinity)`
float\_constant = dec\_float\_constant | hex\_float\_constant | special\_float\_constant
boolean\_constant = `true` | `false`

View File

@@ -1,35 +0,0 @@
# Flatbuffers Intermediate Representation {#intermediate_representation}
We use [reflection.fbs](https://github.com/google/flatbuffers/blob/master/reflection/reflection.fbs)
as our intermediate representation. `flatc` parses `.fbs` files, checks them for
errors and stores the resulting data in this IR, outputting `.bfbs` files.
Since this IR is a Flatbuffer, you can load and use it at runtime for runtime
reflection purposes.
There are some quirks:
- Tables and Structs are serialized as `Object`s.
- Unions and Enums are serialized as `Enum`s.
- It is the responsibility of the code generator to check the `advanced_features`
field of `Schema`. These mark the presence of new, backwards incompatible,
schema features. Code generators must error if generating a schema with
unrecognized advanced features.
- Filenames are relative to a "project root" denoted by "//" in the path. This
may be specified in flatc with `--bfbs-filenames=$PROJECT_ROOT`, or it will be
inferred to be the directory containing the first provided schema file.
## Invocation
You can invoke it like so
```{.sh}
flatc -b --schema ${your_fbs_files}
```
This generates `.bfbs` (binary flatbuffer schema) files.
Some information is not included by default. See the `--bfbs-filenames` and
`--bfbs-comments` flags. These may be necessary for code-generators, so they can
add documentation and maybe name generated files (depending on the generator).
TODO(cneo): Flags to output bfbs as flexbuffers or json.
TODO(cneo): Tutorial for building a flatc plugin.

View File

@@ -1,468 +0,0 @@
FlatBuffer Internals {#flatbuffers_internals}
====================
This section is entirely optional for the use of FlatBuffers. In normal
usage, you should never need the information contained herein. If you're
interested however, it should give you more of an appreciation of why
FlatBuffers is both efficient and convenient.
### Format components
A FlatBuffer is a binary file and in-memory format consisting mostly of
scalars of various sizes, all aligned to their own size. Each scalar is
also always represented in little-endian format, as this corresponds to
all commonly used CPUs today. FlatBuffers will also work on big-endian
machines, but will be slightly slower because of additional
byte-swap intrinsics.
It is assumed that the following conditions are met, to ensure
cross-platform interoperability:
- The binary `IEEE-754` format is used for floating-point numbers.
- The `two's complemented` representation is used for signed integers.
- The endianness is the same for floating-point numbers as for integers.
On purpose, the format leaves a lot of details about where exactly
things live in memory undefined, e.g. fields in a table can have any
order, and objects to some extent can be stored in many orders. This is
because the format doesn't need this information to be efficient, and it
leaves room for optimization and extension (for example, fields can be
packed in a way that is most compact). Instead, the format is defined in
terms of offsets and adjacency only. This may mean two different
implementations may produce different binaries given the same input
values, and this is perfectly valid.
### Format identification
The format also doesn't contain information for format identification
and versioning, which is also by design. FlatBuffers is a statically typed
system, meaning the user of a buffer needs to know what kind of buffer
it is. FlatBuffers can of course be wrapped inside other containers
where needed, or you can use its union feature to dynamically identify
multiple possible sub-objects stored. Additionally, it can be used
together with the schema parser if full reflective capabilities are
desired.
Versioning is something that is intrinsically part of the format (the
optionality / extensibility of fields), so the format itself does not
need a version number (it's a meta-format, in a sense). We're hoping
that this format can accommodate all data needed. If format breaking
changes are ever necessary, it would become a new kind of format rather
than just a variation.
### Offsets
The most important and generic offset type (see `flatbuffers.h`) is
`uoffset_t`, which is currently always a `uint32_t`, and is used to
refer to all tables/unions/strings/vectors (these are never stored
in-line). 32bit is
intentional, since we want to keep the format binary compatible between
32 and 64bit systems, and a 64bit offset would bloat the size for almost
all uses. A version of this format with 64bit (or 16bit) offsets is easy to set
when needed. Unsigned means they can only point in one direction, which
typically is forward (towards a higher memory location). Any backwards
offsets will be explicitly marked as such.
The format starts with an `uoffset_t` to the root table in the buffer.
We have two kinds of objects, structs and tables.
### Structs
These are the simplest, and as mentioned, intended for simple data that
benefits from being extra efficient and doesn't need versioning /
extensibility. They are always stored inline in their parent (a struct,
table, or vector) for maximum compactness. Structs define a consistent
memory layout where all components are aligned to their size, and
structs aligned to their largest scalar member. This is done independent
of the alignment rules of the underlying compiler to guarantee a cross
platform compatible layout. This layout is then enforced in the generated
code.
### Tables
Unlike structs, these are not stored in inline in their parent, but are
referred to by offset.
They start with an `soffset_t` to a vtable. This is a signed version of
`uoffset_t`, since vtables may be stored anywhere relative to the object.
This offset is subtracted (not added) from the object start to arrive at
the vtable start. This offset is followed by all the
fields as aligned scalars (or offsets). Unlike structs, not all fields
need to be present. There is no set order and layout. A table may contain
field offsets that point to the same value if the user explicitly
serializes the same offset twice.
To be able to access fields regardless of these uncertainties, we go
through a vtable of offsets. Vtables are shared between any objects that
happen to have the same vtable values.
The elements of a vtable are all of type `voffset_t`, which is
a `uint16_t`. The first element is the size of the vtable in bytes,
including the size element. The second one is the size of the object, in bytes
(including the vtable offset). This size could be used for streaming, to know
how many bytes to read to be able to access all *inline* fields of the object.
The remaining elements are the N offsets, where N is the amount of fields
declared in the schema when the code that constructed this buffer was
compiled (thus, the size of the table is N + 2).
All accessor functions in the generated code for tables contain the
offset into this table as a constant. This offset is checked against the
first field (the number of elements), to protect against newer code
reading older data. If this offset is out of range, or the vtable entry
is 0, that means the field is not present in this object, and the
default value is return. Otherwise, the entry is used as offset to the
field to be read.
### Unions
Unions are encoded as the combination of two fields: an enum representing the
union choice and the offset to the actual element. FlatBuffers reserves the
enumeration constant `NONE` (encoded as 0) to mean that the union field is not
set.
### Strings and Vectors
Strings are simply a vector of bytes, and are always
null-terminated. Vectors are stored as contiguous aligned scalar
elements prefixed by a 32bit element count (not including any
null termination). Neither is stored inline in their parent, but are referred to
by offset. A vector may consist of more than one offset pointing to the same
value if the user explicitly serializes the same offset twice.
### Construction
The current implementation constructs these buffers backwards (starting
at the highest memory address of the buffer), since
that significantly reduces the amount of bookkeeping and simplifies the
construction API.
### Code example
Here's an example of the code that gets generated for the `samples/monster.fbs`.
What follows is the entire file, broken up by comments:
// automatically generated, do not modify
#include "flatbuffers/flatbuffers.h"
namespace MyGame {
namespace Sample {
Nested namespace support.
enum {
Color_Red = 0,
Color_Green = 1,
Color_Blue = 2,
};
inline const char **EnumNamesColor() {
static const char *names[] = { "Red", "Green", "Blue", nullptr };
return names;
}
inline const char *EnumNameColor(int e) { return EnumNamesColor()[e]; }
Enums and convenient reverse lookup.
enum {
Any_NONE = 0,
Any_Monster = 1,
};
inline const char **EnumNamesAny() {
static const char *names[] = { "NONE", "Monster", nullptr };
return names;
}
inline const char *EnumNameAny(int e) { return EnumNamesAny()[e]; }
Unions share a lot with enums.
struct Vec3;
struct Monster;
Predeclare all data types since circular references between types are allowed
(circular references between object are not, though).
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 {
private:
float x_;
float y_;
float z_;
public:
Vec3(float x, float y, float z)
: x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) {}
float x() const { return flatbuffers::EndianScalar(x_); }
float y() const { return flatbuffers::EndianScalar(y_); }
float z() const { return flatbuffers::EndianScalar(z_); }
};
FLATBUFFERS_STRUCT_END(Vec3, 12);
These ugly macros do a couple of things: they turn off any padding the compiler
might normally do, since we add padding manually (though none in this example),
and they enforce alignment chosen by FlatBuffers. This ensures the layout of
this struct will look the same regardless of compiler and platform. Note that
the fields are private: this is because these store little endian scalars
regardless of platform (since this is part of the serialized data).
`EndianScalar` then converts back and forth, which is a no-op on all current
mobile and desktop platforms, and a single machine instruction on the few
remaining big endian platforms.
struct Monster : private flatbuffers::Table {
const Vec3 *pos() const { return GetStruct<const Vec3 *>(4); }
int16_t mana() const { return GetField<int16_t>(6, 150); }
int16_t hp() const { return GetField<int16_t>(8, 100); }
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(10); }
const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(14); }
int8_t color() const { return GetField<int8_t>(16, 2); }
};
Tables are a bit more complicated. A table accessor struct is used to point at
the serialized data for a table, which always starts with an offset to its
vtable. It derives from `Table`, which contains the `GetField` helper functions.
GetField takes a vtable offset, and a default value. It will look in the vtable
at that offset. If the offset is out of bounds (data from an older version) or
the vtable entry is 0, the field is not present and the default is returned.
Otherwise, it uses the entry as an offset into the table to locate the field.
struct MonsterBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); }
void add_mana(int16_t mana) { fbb_.AddElement<int16_t>(6, mana, 150); }
void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(8, hp, 100); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(10, name); }
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(14, inventory); }
void add_color(int8_t color) { fbb_.AddElement<int8_t>(16, color, 2); }
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
flatbuffers::Offset<Monster> Finish() { return flatbuffers::Offset<Monster>(fbb_.EndTable(start_, 7)); }
};
`MonsterBuilder` is the base helper struct to construct a table using a
`FlatBufferBuilder`. You can add the fields in any order, and the `Finish`
call will ensure the correct vtable gets generated.
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos, int16_t mana,
int16_t hp,
flatbuffers::Offset<flatbuffers::String> name,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory,
int8_t color) {
MonsterBuilder builder_(_fbb);
builder_.add_inventory(inventory);
builder_.add_name(name);
builder_.add_pos(pos);
builder_.add_hp(hp);
builder_.add_mana(mana);
builder_.add_color(color);
return builder_.Finish();
}
`CreateMonster` is a convenience function that calls all functions in
`MonsterBuilder` above for you. Note that if you pass values which are
defaults as arguments, it will not actually construct that field, so
you can probably use this function instead of the builder class in
almost all cases.
inline const Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<Monster>(buf); }
This function is only generated for the root table type, to be able to
start traversing a FlatBuffer from a raw buffer pointer.
}; // namespace MyGame
}; // namespace Sample
### Encoding example.
Below is a sample encoding for the following JSON corresponding to the above
schema:
{ pos: { x: 1, y: 2, z: 3 }, name: "fred", hp: 50 }
Resulting in this binary buffer:
// Start of the buffer:
uint32_t 20 // Offset to the root table.
// Start of the vtable. Not shared in this example, but could be:
uint16_t 16 // Size of table, starting from here.
uint16_t 22 // Size of object inline data.
uint16_t 4, 0, 20, 16, 0, 0 // Offsets to fields from start of (root) table, 0 for not present.
// Start of the root table:
int32_t 16 // Offset to vtable used (default negative direction)
float 1, 2, 3 // the Vec3 struct, inline.
uint32_t 8 // Offset to the name string.
int16_t 50 // hp field.
int16_t 0 // Padding for alignment.
// Start of name string:
uint32_t 4 // Length of string.
int8_t 'f', 'r', 'e', 'd', 0, 0, 0, 0 // Text + 0 termination + padding.
Note that this not the only possible encoding, since the writer has some
flexibility in which of the children of root object to write first (though in
this case there's only one string), and what order to write the fields in.
Different orders may also cause different alignments to happen.
### Additional reading.
The author of the C language implementation has made a similar
[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format)
that may further help clarify the format.
# FlexBuffers
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
own encoding, detailed here.
It shares many properties mentioned above, in that all data is accessed
over offsets, all scalars are aligned to their own size, and
all data is always stored in little endian format.
One difference is that FlexBuffers are built front to back, so children are
stored before parents, and the root of the data starts at the last byte.
Another difference is that scalar data is stored with a variable number of bits
(8/16/32/64). The current width is always determined by the *parent*, i.e. if
the scalar sits in a vector, the vector determines the bit width for all
elements at once. Selecting the minimum bit width for a particular vector is
something the encoder does automatically and thus is typically of no concern
to the user, though being aware of this feature (and not sticking a double in
the same vector as a bunch of byte sized elements) is helpful for efficiency.
Unlike FlatBuffers there is only one kind of offset, and that is an unsigned
integer indicating the number of bytes in a negative direction from the address
of itself (where the offset is stored).
### Vectors
The representation of the vector is at the core of how FlexBuffers works (since
maps are really just a combination of 2 vectors), so it is worth starting there.
As mentioned, a vector is governed by a single bit width (supplied by its
parent). This includes the size field. For example, a vector that stores the
integer values `1, 2, 3` is encoded as follows:
uint8_t 3, 1, 2, 3, 4, 4, 4
The first `3` is the size field, and is placed before the vector (an offset
from the parent to this vector points to the first element, not the size
field, so the size field is effectively at index -1).
Since this is an untyped vector `SL_VECTOR`, it is followed by 3 type
bytes (one per element of the vector), which are always following the vector,
and are always a uint8_t even if the vector is made up of bigger scalars.
A vector may include more than one offset pointing to the same value if the
user explicitly serializes the same offset twice.
### Types
A type byte is made up of 2 components (see flexbuffers.h for exact values):
* 2 lower bits representing the bit-width of the child (8, 16, 32, 64).
This is only used if the child is accessed over an offset, such as a child
vector. It is ignored for inline types.
* 6 bits representing the actual type (see flexbuffers.h).
Thus, in this example `4` means 8 bit child (value 0, unused, since the value is
in-line), type `SL_INT` (value 1).
### Typed Vectors
These are like the Vectors above, but omit the type bytes. The type is instead
determined by the vector type supplied by the parent. Typed vectors are only
available for a subset of types for which these savings can be significant,
namely inline signed/unsigned integers (`TYPE_VECTOR_INT` / `TYPE_VECTOR_UINT`),
floats (`TYPE_VECTOR_FLOAT`), and keys (`TYPE_VECTOR_KEY`, see below).
Additionally, for scalars, there are fixed length vectors of sizes 2 / 3 / 4
that don't store the size (`TYPE_VECTOR_INT2` etc.), for an additional savings
in space when storing common vector or color data.
### Scalars
FlexBuffers supports integers (`TYPE_INT` and `TYPE_UINT`) and floats
(`TYPE_FLOAT`), available in the bit-widths mentioned above. They can be stored
both inline and over an offset (`TYPE_INDIRECT_*`).
The offset version is useful to encode costly 64bit (or even 32bit) quantities
into vectors / maps of smaller sizes, and to share / repeat a value multiple
times.
### Booleans and Nulls
Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers.
### Blobs, Strings and Keys.
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
elements are always `uint8_t`. The parent bit width only determines the width of
the size field, allowing blobs to be large without the elements being large.
Strings (`TYPE_STRING`) are similar to blobs, except they have an additional 0
termination byte for convenience, and they MUST be UTF-8 encoded (since an
accessor in a language that does not support pointers to UTF-8 data may have to
convert them to a native string type).
A "Key" (`TYPE_KEY`) is similar to a string, but doesn't store the size
field. They're so named because they are used with maps, which don't care
for the size, and can thus be even more compact. Unlike strings, keys cannot
contain bytes of value 0 as part of their data (size can only be determined by
`strlen`), so while you can use them outside the context of maps if you so
desire, you're usually better off with strings.
### Maps
A map (`TYPE_MAP`) is like an (untyped) vector, but with 2 prefixes before the
size field:
| index | field |
| ----: | :----------------------------------------------------------- |
| -3 | An offset to the keys vector (may be shared between tables). |
| -2 | Byte width of the keys vector. |
| -1 | Size (from here on it is compatible with `TYPE_VECTOR`) |
| 0 | Elements. |
| Size | Types. |
Since a map is otherwise the same as a vector, it can be iterated like
a vector (which is probably faster than lookup by key).
The keys vector is a typed vector of keys. Both the keys and corresponding
values *have* to be stored in sorted order (as determined by `strcmp`), such
that lookups can be made using binary search.
The reason the key vector is a separate structure from the value vector is
such that it can be shared between multiple value vectors, and also to
allow it to be treated as its own individual vector in code.
An example map { foo: 13, bar: 14 } would be encoded as:
0 : uint8_t 'b', 'a', 'r', 0
4 : uint8_t 'f', 'o', 'o', 0
8 : uint8_t 2 // key vector of size 2
// key vector offset points here
9 : uint8_t 9, 6 // offsets to bar_key and foo_key
11: uint8_t 2, 1 // offset to key vector, and its byte width
13: uint8_t 2 // value vector of size
// value vector offset points here
14: uint8_t 14, 13 // values
16: uint8_t 4, 4 // types
### The root
As mentioned, the root starts at the end of the buffer.
The last uint8_t is the width in bytes of the root (normally the parent
determines the width, but the root has no parent). The uint8_t before this is
the type of the root, and the bytes before that are the root value (of the
number of bytes specified by the last byte).
So for example, the integer value `13` as root would be:
uint8_t 13, 4, 1 // Value, type, root byte width.
<br>

View File

@@ -1,93 +0,0 @@
Use in JavaScript {#flatbuffers_guide_use_javascript}
=================
## Before you get started
Before diving into the FlatBuffers usage in JavaScript, 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 JavaScript). This page is specifically designed to cover the nuances
of FlatBuffers usage in JavaScript.
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 JavaScript library code location
The generated code for the FlatBuffers JavaScript library can be found at
https://www.npmjs.com/package/flatbuffers. To use it from sources:
1. Run `npm run compile` from the main folder to generate JS files from TS.
1. In your project, install it as a normal dependency, using the flatbuffers
folder as the source.
## Using the FlatBuffers JavaScript library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers.*
Due to the complexity related with large amounts of JS flavors and module types,
native JS support has been replaced in 2.0 by transpilation from TypeScript.
Please look at [TypeScript usage](@ref flatbuffers_guide_use_typescript) and
transpile your sources to desired JS flavor. The minimal steps to get up and
running with JS are:
1. Generate TS files from `*.fbs` by using the `--ts` option.
1. Transpile resulting TS files to desired JS flavor using `tsc` (see
https://www.typescriptlang.org/download for installation instructions).
~~~{.js}
// Note: These require functions are an example - use your desired module flavor.
var fs = require('fs');
var flatbuffers = require('../flatbuffers').flatbuffers;
var MyGame = require('./monster_generated').MyGame;
var data = new Uint8Array(fs.readFileSync('monster.dat'));
var buf = new flatbuffers.ByteBuffer(data);
var monster = MyGame.Example.Monster.getRootAsMonster(buf);
//--------------------------------------------------------------------------//
// Note: This code is an example of browser-based HTML/JavaScript. See above
// for the code using JavaScript module loaders (e.g. Node.js).
<script src="../js/flatbuffers.js"></script>
<script src="monster_generated.js"></script>
<script>
function readFile() {
var reader = new FileReader(); // This example uses the HTML5 FileReader.
var file = document.getElementById(
'file_input').files[0]; // "monster.dat" from the HTML <input> field.
reader.onload = function() { // Executes after the file is read.
var data = new Uint8Array(reader.result);
var buf = new flatbuffers.ByteBuffer(data);
var monster = MyGame.Example.Monster.getRootAsMonster(buf);
}
reader.readAsArrayBuffer(file);
}
</script>
// Open the HTML file in a browser and select "monster.dat" from with the
// <input> field.
<input type="file" id="file_input" onchange="readFile();">
~~~
Now you can access values like this:
~~~{.js}
var hp = monster.hp();
var pos = monster.pos();
~~~
## Text parsing FlatBuffers in JavaScript
There currently is no support for parsing text (Schema's and JSON) directly
from JavaScript.

View File

@@ -1,114 +0,0 @@
Use in Java {#flatbuffers_guide_use_java}
==============
## Before you get started
Before diving into the FlatBuffers usage in Java, 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 Java).
This page is designed to cover the nuances of FlatBuffers usage,
specific to Java.
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 Java code location
The code for the FlatBuffers Java library can be found at
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
java/com/google/flatbuffers).
## Testing the FlatBuffers Java libraries
The code to test the libraries can be found at `flatbuffers/tests`.
The test code for Java is located in [JavaTest.java](https://github.com/google
/flatbuffers/blob/master/tests/JavaTest.java).
To run the tests, use either [JavaTest.sh](https://github.com/google/
flatbuffers/blob/master/tests/JavaTest.sh) or [JavaTest.bat](https://github.com/
google/flatbuffers/blob/master/tests/JavaTest.bat), depending on your operating
system.
*Note: These scripts require that [Java](https://www.oracle.com/java/index.html)
is installed.*
## Using the FlatBuffers Java library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Java.*
FlatBuffers supports reading and writing binary FlatBuffers in Java.
To use FlatBuffers in your own code, first generate Java classes from your
schema with the `--java` 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 Java:
First, import the library and generated code. Then, you read a FlatBuffer binary
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
pass to the `getRootAsMyRootType` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
import MyGame.Example.*;
import com.google.flatbuffers.FlatBufferBuilder;
// This snippet ignores exceptions for brevity.
File file = new File("monsterdata_test.mon");
RandomAccessFile f = new RandomAccessFile(file, "r");
byte[] data = new byte[(int)f.length()];
f.readFully(data);
f.close();
ByteBuffer bb = ByteBuffer.wrap(data);
Monster monster = Monster.getRootAsMonster(bb);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access the data from the `Monster monster`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
short hp = monster.hp();
Vec3 pos = monster.pos();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Storing dictionaries in a FlatBuffer
FlatBuffers doesn't support dictionaries natively, but there is support to
emulate their behavior with vectors and binary search, which means you
can have fast lookups directly from a FlatBuffer without having to unpack
your data into a `Dictionary` or similar.
To use it:
- Designate one of the fields in a table as the "key" field. You do this
by setting the `key` attribute on this field, e.g.
`name:string (key)`.
You may only have one key field, and it must be of string or scalar type.
- Write out tables of this type as usual, collect their offsets in an
array.
- Instead of calling standard generated method,
e.g.: `Monster.createTestarrayoftablesVector`,
call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object).
which will first sort all offsets such that the tables they refer to
are sorted by the key field, then serialize it.
- Now when you're accessing the FlatBuffer, you can use
the `ByKey` accessor to access elements of the vector, e.g.:
`monster.testarrayoftablesByKey("Frodo")`.
which returns an object of the corresponding table type,
or `null` if not found.
`ByKey` performs a binary search, so should have a similar
speed to `Dictionary`, though may be faster because of better caching.
`ByKey` only works if the vector has been sorted, it will
likely not find elements if it hasn't been sorted.
## Text parsing
There currently is no support for parsing text (Schema's and JSON) directly
from Java, though you could use the C++ parser through native call
interfaces available to each language. Please see the
C++ documentation for more on text parsing.
<br>

View File

@@ -1,84 +0,0 @@
Use in Kotlin {#flatbuffers_guide_use_kotlin}
==============
## Before you get started
Before diving into the FlatBuffers usage in Kotlin, 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 K).
This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin.
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).
## Kotlin and FlatBuffers Java code location
Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported.
The code for the FlatBuffers Java library can be found at
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
java/com/google/flatbuffers).
## Testing FlatBuffers Kotlin
The test code for Java is located in [KotlinTest.java](https://github.com/google
/flatbuffers/blob/master/tests/KotlinTest.kt).
To run the tests, use [KotlinTest.sh](https://github.com/google/
flatbuffers/blob/master/tests/KotlinTest.sh) shell script.
*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.*
## Using the FlatBuffers Kotlin library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Kotlin.*
FlatBuffers supports reading and writing binary FlatBuffers in Kotlin.
To use FlatBuffers in your own code, first generate Java classes from your
schema with the `--kotlin` 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 Kotlin:
First, import the library and generated code. Then, you read a FlatBuffer binary
file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you
pass to the `getRootAsMyRootType` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
import MyGame.Example.*
import com.google.flatbuffers.FlatBufferBuilder
// This snippet ignores exceptions for brevity.
val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use {
val temp = ByteArray(it.length().toInt())
it.readFully(temp)
temp
}
val bb = ByteBuffer.wrap(data)
val monster = Monster.getRootAsMonster(bb)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access the data from the `Monster monster`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
val hp = monster.hp
val pos = monster.pos!!;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Differences between Kotlin and Java code
Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html).
The most obvious ones are:
* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html)
* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects)

View File

@@ -1,85 +0,0 @@
Use in Lobster {#flatbuffers_guide_use_lobster}
==============
## Before you get started
Before diving into the FlatBuffers usage in Lobster, 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 Lobster). This
page is designed to cover the nuances of FlatBuffers usage, specific to
Lobster.
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 Lobster library code location
The code for the FlatBuffers Lobster library can be found at
`flatbuffers/lobster`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
lobster).
## Testing the FlatBuffers Lobster library
The code to test the Lobster library can be found at `flatbuffers/tests`.
The test code itself is located in [lobstertest.lobster](https://github.com/google/
flatbuffers/blob/master/tests/lobstertest.lobster).
To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself,
go to the [Lobster homepage](http://strlen.com/lobster) or
[github](https://github.com/aardappel/lobster) to learn how to build it for your
platform.
## Using the FlatBuffers Lobster library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Lobster.*
There is support for both reading and writing FlatBuffers in Lobster.
To use FlatBuffers in your own code, first generate Lobster classes from your
schema with the `--lobster` 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 Lobster:
First, import the library and the generated code. Then read a FlatBuffer binary
file into a string, which you pass to the `GetRootAsMonster` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
include "monster_generated.lobster"
let fb = read_file("monsterdata_test.mon")
assert fb
let monster = MyGame_Example_GetRootAsMonster(fb)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
let hp = monster.hp
let pos = monster.pos
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you can see, even though `hp` and `pos` are functions that access FlatBuffer
data in-place in the string buffer, they appear as field accesses.
## Speed
Using FlatBuffers in Lobster should be relatively fast, as the implementation
makes use of native support for writing binary values, and access of vtables.
Both generated code and the runtime library are therefore small and fast.
Actual speed will depend on whether you use Lobster as bytecode VM or compiled to
C++.
## Text Parsing
Lobster has full support for parsing JSON into FlatBuffers, or generating
JSON from FlatBuffers. See `samples/sample_test.lobster` for an example.
This uses the C++ parser and generator underneath, so should be both fast and
conformant.
<br>

View File

@@ -1,81 +0,0 @@
Use in Lua {#flatbuffers_guide_use_lua}
=============
## Before you get started
Before diving into the FlatBuffers usage in Lua, 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 Lua). This
page is designed to cover the nuances of FlatBuffers usage, specific to
Lua.
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 Lua library code location
The code for the FlatBuffers Lua library can be found at
`flatbuffers/lua`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua).
## Testing the FlatBuffers Lua library
The code to test the Lua library can be found at `flatbuffers/tests`.
The test code itself is located in [luatest.lua](https://github.com/google/
flatbuffers/blob/master/tests/luatest.lua).
To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/
blob/master/tests/LuaTest.sh) shell script.
*Note: This script requires [Lua 5.3](https://www.lua.org/) and
[LuaJIT](http://luajit.org/) to be installed.*
## Using the FlatBuffers Lua library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Lua.*
There is support for both reading and writing FlatBuffers in Lua.
To use FlatBuffers in your own code, first generate Lua classes from your
schema with the `--lua` 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 Lua:
First, require the module and the generated code. Then read a FlatBuffer binary
file into a `string`, which you pass to the `GetRootAsMonster` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
-- require the library
local flatbuffers = require("flatbuffers")
-- require the generated code
local monster = require("MyGame.Sample.Monster")
-- read the flatbuffer from a file into a string
local f = io.open('monster.dat', 'rb')
local buf = f:read('*a')
f:close()
-- parse the flatbuffer to get an instance to the root monster
local monster1 = monster.GetRootAsMonster(buf, 0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
-- use the : notation to access member data
local hp = monster1:Hp()
local pos = monster1:Pos()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly
from Lua, though you could use the C++ parser through SWIG or ctypes. Please
see the C++ documentation for more on text parsing.
<br>

View File

@@ -1,89 +0,0 @@
Use in PHP {#flatbuffers_guide_use_php}
==========
## Before you get started
Before diving into the FlatBuffers usage in PHP, 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 PHP). This page is specifically designed to cover the nuances of
FlatBuffers usage in PHP.
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 PHP library code location
The code for FlatBuffers PHP library can be found at `flatbuffers/php`. You
can browse the library code on the [FlatBuffers
GitHub page](https://github.com/google/flatbuffers/tree/master/php).
## Testing the FlatBuffers JavaScript library
The code to test the PHP library can be found at `flatbuffers/tests`.
The test code itself is located in [phpTest.php](https://github.com/google/
flatbuffers/blob/master/tests/phpTest.php).
You can run the test with `php phpTest.php` from the command line.
*Note: The PHP test file requires
[PHP](http://php.net/manual/en/install.php) to be installed.*
## Using theFlatBuffers PHP library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in PHP.*
FlatBuffers supports both reading and writing FlatBuffers in PHP.
To use FlatBuffers in your own code, first generate PHP classes from your schema
with the `--php` 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 PHP:
First, include the library and generated code (using the PSR `autoload`
function). Then you can read a FlatBuffer binary file, which you
pass the contents of to the `GetRootAsMonster` function:
~~~{.php}
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
// Here is an example:
function __autoload($class_name) {
// The last segment of the class name matches the file name.
$class = substr($class_name, strrpos($class_name, "\\") + 1);
$root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); // `flatbuffers` root.
// Contains the `*.php` files for the FlatBuffers library and the `flatc` generated files.
$paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")),
join(DIRECTORY_SEPARATOR, array($root_dir, "tests", "MyGame", "Example")));
foreach ($paths as $path) {
$file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php"));
if (file_exists($file)) {
require($file);
break;
}
}
// Read the contents of the FlatBuffer binary file.
$filename = "monster.dat";
$handle = fopen($filename, "rb");
$contents = $fread($handle, filesize($filename));
fclose($handle);
// Pass the contents to `GetRootAsMonster`.
$monster = \MyGame\Example\Monster::GetRootAsMonster($contents);
~~~
Now you can access values like this:
~~~{.php}
$hp = $monster->GetHp();
$pos = $monster->GetPos();
~~~
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly
from PHP.

View File

@@ -1,100 +0,0 @@
Use in Python {#flatbuffers_guide_use_python}
=============
## Before you get started
Before diving into the FlatBuffers usage in Python, 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 Python). This
page is designed to cover the nuances of FlatBuffers usage, specific to
Python.
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 Python library code location
The code for the FlatBuffers Python library can be found at
`flatbuffers/python/flatbuffers`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
python).
## Testing the FlatBuffers Python library
The code to test the Python library can be found at `flatbuffers/tests`.
The test code itself is located in [py_test.py](https://github.com/google/
flatbuffers/blob/master/tests/py_test.py).
To run the tests, use the [PythonTest.sh](https://github.com/google/flatbuffers/
blob/master/tests/PythonTest.sh) shell script.
*Note: This script requires [python](https://www.python.org/) to be
installed.*
## Using the FlatBuffers Python library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Python.*
There is support for both reading and writing FlatBuffers in Python.
To use FlatBuffers in your own code, first generate Python classes from your
schema with the `--python` 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 Python:
First, import the library and the generated code. Then read a FlatBuffer binary
file into a `bytearray`, which you pass to the `GetRootAsMonster` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
import MyGame.Example as example
import flatbuffers
buf = open('monster.dat', 'rb').read()
buf = bytearray(buf)
monster = example.GetRootAsMonster(buf, 0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
hp = monster.Hp()
pos = monster.Pos()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Support for Numpy arrays
The Flatbuffers python library also has support for accessing scalar
vectors as numpy arrays. This can be orders of magnitude faster than
iterating over the vector one element at a time, and is particularly
useful when unpacking large nested flatbuffers. The generated code for
a scalar vector will have a method `<vector name>AsNumpy()`. In the
case of the Monster example, you could access the inventory vector
like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
inventory = monster.InventoryAsNumpy()
# inventory is a numpy array of type np.dtype('uint8')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
instead of
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
inventory = []
for i in range(monster.InventoryLength()):
inventory.append(int(monster.Inventory(i)))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Numpy is not a requirement. If numpy is not installed on your system,
then attempting to access one of the `*asNumpy()` methods will result
in a `NumpyRequiredForThisFeature` exception.
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly
from Python, though you could use the C++ parser through SWIG or ctypes. Please
see the C++ documentation for more on text parsing.
<br>

View File

@@ -1,32 +0,0 @@
## Prerequisites
To generate the docs for FlatBuffers from the source files, you
will first need to install two programs.
1. You will need to install `doxygen`. See
[Download Doxygen](https://doxygen.nl/download.html).
2. You will need to install `doxypypy` to format python comments appropriately.
Install it from [here](https://github.com/Feneric/doxypypy).
*Note: You will need both `doxygen` and `doxypypy` to be in your
[PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable.*
After you have both of those files installed and in your path, you need to
set up the `py_filter` to invoke `doxypypy` from `doxygen`.
Follow the steps
[here](https://github.com/Feneric/doxypypy#invoking-doxypypy-from-doxygen).
## Generating Docs
Run the following commands to generate the docs:
`cd flatbuffers/docs/source`
`doxygen`
The output is placed in `flatbuffers/docs/html`.
*Note: The Go API Reference code must be generated ahead of time. For
instructions on how to regenerated this file, please read the comments
in `GoApi.md`.*

View File

@@ -1,186 +0,0 @@
Use in Rust {#flatbuffers_guide_use_rust}
==========
## Before you get started
Before diving into the FlatBuffers usage in Rust, 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 Rust).
This page is designed to cover the nuances of FlatBuffers usage, specific to
Rust.
#### Prerequisites
This page assumes you have written a FlatBuffers schema and compiled it
with the Schema Compiler. If you have not, please see
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
matter), you've generated a Rust file called `mygame_generated.rs` using the
compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful
tools created by others" section bellow), you can now start using this in
your program by including the file. As noted, this header relies on the crate
`flatbuffers`, which should be in your include `Cargo.toml`.
## FlatBuffers Rust library code location
The code for the FlatBuffers Rust library can be found at
`flatbuffers/rust`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
## Testing the FlatBuffers Rust library
The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
The test code itself is located in
[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
This test file requires `flatc` to be present. To review how to build the project,
please read the [Building](@ref flatbuffers_guide_building) documentation.
To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
run: `cd tests && ./RustTest.sh`.
*Note: The shell script requires [Rust](https://www.rust-lang.org) to
be installed.*
## Using the FlatBuffers Rust library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Rust.*
FlatBuffers supports both reading and writing FlatBuffers in Rust.
To use FlatBuffers in your code, first generate the Rust modules from your
schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
and the generated code to read or write FlatBuffers.
For example, here is how you would read a FlatBuffer binary file in Rust:
First, include the library and generated code. Then read the file into
a `u8` vector, which you pass, as a byte slice, to `root_as_monster()`.
This full example program is available in the Rust test suite:
[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
extern crate flatbuffers;
#[allow(dead_code, unused_imports)]
#[path = "../../monster_test_generated.rs"]
mod monster_test_generated;
pub use monster_test_generated::my_game;
use std::io::Read;
fn main() {
let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
let mut buf = Vec::new();
f.read_to_end(&mut buf).expect("file reading failed");
let monster = my_game::example::root_as_monster(&buf[..]);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`monster` is of type `Monster`, and points to somewhere *inside* your
buffer (root object pointers are not the same as `buffer_pointer` !).
If you look in your generated header, you'll see it has
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
println!("{}", monster.hp()); // `80`
println!("{}", monster.mana()); // default value of `150`
println!("{:?}", monster.name()); // Some("MyMonster")
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*Note: That we never stored a `mana` value, so it will return the default.*
## Direct memory access
As you can see from the above examples, all elements in a buffer are
accessed through generated accessors. This is because everything is
stored in little endian format on all platforms (the accessor
performs a swap operation on big endian machines), and also because
the layout of things is generally not known to the user.
For structs, layout is deterministic and guaranteed to be the same
across platforms (scalars are aligned to their
own size, and structs themselves to their largest member), and you
are allowed to access this memory directly by using `safe_slice`
on the reference to a struct, or even an array of structs.
To compute offsets to sub-elements of a struct, make sure they
are structs themselves, as then you can use the pointers to
figure out the offset without having to hardcode it. This is
handy for use of arrays of structs with calls like `glVertexAttribPointer`
in OpenGL or similar APIs.
It is important to note is that structs are still little endian on all
machines, so the functions to enable tricks like this are only exposed on little
endian machines. If you also ship on big endian machines, using an
`#[cfg(target_endian = "little")]` attribute would be wise or your code will not
compile.
The special function `safe_slice` is implemented on Vector objects that are
represented in memory the same way as they are represented on the wire. This
function is always available on vectors of struct, bool, u8, and i8. It is
conditionally-compiled on little-endian systems for all the remaining scalar
types.
The FlatBufferBuilder function `create_vector_direct` is implemented for all
types that are endian-safe to write with a `memcpy`. It is the write-equivalent
of `safe_slice`.
## Access of untrusted buffers
The safe Rust functions to interpret a slice as a table (`root`,
`size_prefixed_root`, `root_with_opts`, and `size_prefixed_root_with_opts`)
verify the data first. This has some performance cost, but is intended to be
safe for use on flatbuffers from untrusted sources. There are corresponding
`unsafe` versions with names ending in `_unchecked` which skip this
verification, and may access arbitrary memory.
The generated accessor functions access fields over offsets, which is
very quick. The current implementation uses these to access memory without any
further bounds checking. All of the safe Rust APIs ensure the verifier is run
over these flatbuffers before accessing them.
When you're processing large amounts of data from a source you know (e.g.
your own generated data on disk), the `_unchecked` versions are acceptable, but
when reading data from the network that can potentially have been modified by an
attacker, it is desirable to use the safe versions which use the verifier.
## Threading
Reading a FlatBuffer does not touch any memory outside the original buffer,
and is entirely read-only (all immutable), so is safe to access from multiple
threads even without synchronisation primitives.
Creating a FlatBuffer is not thread safe. All state related to building
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
outside of it is touched. To make this thread safe, either do not
share instances of FlatBufferBuilder between threads (recommended), or
manually wrap it in synchronisation primitives. There's no automatic way to
accomplish this, by design, as we feel multithreaded construction
of a single buffer will be rare, and synchronisation overhead would be costly.
Unlike most other languages, in Rust these properties are exposed to and
enforced by the type system. `flatbuffers::Table` and the generated table types
are `Send + Sync`, indicating they may be freely shared across threads and data
may be accessed from any thread which receives a const (aka shared) reference.
There are no functions which require a mutable (aka exclusive) reference, which
means all the available functions may be called like this.
`flatbuffers::FlatBufferBuilder` is also `Send + Sync`, but all of the mutating
functions require a mutable (aka exclusive) reference which can only be created
when no other references to the `FlatBufferBuilder` exist, and may not be copied
within the same thread, let alone to a second thread.
## Useful tools created by others
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo
build scripts integration.
<br>

View File

@@ -1,685 +0,0 @@
Writing a schema {#flatbuffers_guide_writing_schema}
================
The syntax of the schema language (aka IDL, [Interface Definition Language][])
should look quite familiar to users of any of the C family of
languages, and also to users of other IDLs. Let's look at an example
first:
// example IDL file
namespace MyGame;
attribute "priority";
enum Color : byte { Red = 1, Green, Blue }
union Any { Monster, Weapon, Pickup }
struct Vec3 {
x:float;
y:float;
z:float;
}
table Monster {
pos:Vec3;
mana:short = 150;
hp:short = 100;
name:string;
friendly:bool = false (deprecated, priority: 1);
inventory:[ubyte];
color:Color = Blue;
test:Any;
}
root_type Monster;
(`Weapon` & `Pickup` not defined as part of this example).
### Tables
Tables are the main way of defining objects in FlatBuffers, and consist of a
name (here `Monster`) and a list of fields. Each field has a name, a type, and
optionally a default value. If the default value is not specified in the schema,
it will be `0` for scalar types, or `null` for other types. Some languages
support setting a scalar's default to `null`. This makes the scalar optional.
Fields do not have to appear in the wire representation, and you can choose
to omit fields when constructing an object. You have the flexibility to add
fields without fear of bloating your data. This design is also FlatBuffer's
mechanism for forward and backwards compatibility. Note that:
- You can add new fields in the schema ONLY at the end of a table
definition. Older data will still
read correctly, and give you the default value when read. Older code
will simply ignore the new field.
If you want to have flexibility to use any order for fields in your
schema, you can manually assign ids (much like Protocol Buffers),
see the `id` attribute below.
- You cannot delete fields you don't use anymore from the schema,
but you can simply
stop writing them into your data for almost the same effect.
Additionally you can mark them as `deprecated` as in the example
above, which will prevent the generation of accessors in the
generated C++, as a way to enforce the field not being used any more.
(careful: this may break code!).
- You may change field names and table names, if you're ok with your
code breaking until you've renamed them there too.
See "Schema evolution examples" below for more on this
topic.
### Structs
Similar to a table, only now none of the fields are optional (so no defaults
either), and fields may not be added or be deprecated. Structs may only contain
scalars or other structs. Use this for
simple objects where you are very sure no changes will ever be made
(as quite clear in the example `Vec3`). Structs use less memory than
tables and are even faster to access (they are always stored in-line in their
parent object, and use no virtual table).
### Types
Built-in scalar types are
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
- 16 bit: `short` (`int16`), `ushort` (`uint16`)
- 32 bit: `int` (`int32`), `uint` (`uint32`), `float` (`float32`)
- 64 bit: `long` (`int64`), `ulong` (`uint64`), `double` (`float64`)
The type names in parentheses are alias names such that for example
`uint8` can be used in place of `ubyte`, and `int32` can be used in
place of `int` without affecting code generation.
Built-in non-scalar types:
- Vector of any other type (denoted with `[type]`). Nesting vectors
is not supported, instead you can wrap the inner vector in a table.
- `string`, which may only hold UTF-8 or 7-bit ASCII. For other text encodings
or general binary data use vectors (`[byte]` or `[ubyte]`) instead.
- References to other tables or structs, enums or unions (see
below).
You can't change types of fields once they're used, with the exception
of same-size data where a `reinterpret_cast` would give you a desirable result,
e.g. you could change a `uint` to an `int` if no values in current data use the
high bit yet.
### Arrays
Arrays are a convenience short-hand for a fixed-length collection of elements.
Arrays can be used to replace the following schema:
struct Vec3 {
x:float;
y:float;
z:float;
}
with the following schema:
struct Vec3 {
v:[float:3];
}
Both representations are binary equivalent.
Arrays are currently only supported in a `struct`.
### Default, Optional and Required Values
There are three, mutually exclusive, reactions to the non-presence of a table's
field in the binary data:
1. Default valued fields will return the default value (as defined in the schema).
2. Optional valued fields will return some form of `null` depending on the
local language. (In a sense, `null` is the default value).
3. Required fields will cause an error. Flatbuffer verifiers would
consider the whole buffer invalid. See the `required` tag below.
When writing a schema, values are a sequence of digits. Values may be optionally
followed by a decimal point (`.`) and more digits, for float constants, or
optionally prefixed by a `-`. Floats may also be in scientific notation;
optionally ending with an `e` or `E`, followed by a `+` or `-` and more digits.
Values can also be the keyword `null`.
Only scalar values can have defaults, non-scalar (string/vector/table) fields
default to `null` when not present.
You generally do not want to change default values after they're initially
defined. Fields that have the default value are not actually stored in the
serialized data (see also Gotchas below). Values explicitly written by code
generated by the old schema old version, if they happen to be the default, will
be read as a different value by code generated with the new schema. This is
slightly less bad when converting an optional scalar into a default valued
scalar since non-presence would not be overloaded with a previous default value.
There are situations, however, where this may be desirable, especially if you
can ensure a simultaneous rebuild of all code.
### Enums
Define a sequence of named constants, each with a given value, or
increasing by one from the previous one. The default first value
is `0`. As you can see in the enum declaration, you specify the underlying
integral type of the enum with `:` (in this case `byte`), which then determines
the type of any fields declared with this enum type.
Only integer types are allowed, i.e. `byte`, `ubyte`, `short` `ushort`, `int`,
`uint`, `long` and `ulong`.
Typically, enum values should only ever be added, never removed (there is no
deprecation for enums). This requires code to handle forwards compatibility
itself, by handling unknown enum values.
### Unions
Unions share a lot of properties with enums, but instead of new names
for constants, you use names of tables. You can then declare
a union field, which can hold a reference to any of those types, and
additionally a field with the suffix `_type` is generated that holds
the corresponding enum value, allowing you to know which type to cast
to at runtime.
It's possible to give an alias name to a type union. This way a type can even be
used to mean different things depending on the name used:
table PointPosition { x:uint; y:uint; }
table MarkerPosition {}
union Position {
Start:MarkerPosition,
Point:PointPosition,
Finish:MarkerPosition
}
Unions contain a special `NONE` marker to denote that no value is stored so that
name cannot be used as an alias.
Unions are a good way to be able to send multiple message types as a FlatBuffer.
Note that because a union field is really two fields, it must always be
part of a table, it cannot be the root of a FlatBuffer by itself.
If you have a need to distinguish between different FlatBuffers in a more
open-ended way, for example for use as files, see the file identification
feature below.
There is an experimental support only in C++ for a vector of unions (and
types). In the example IDL file above, use [Any] to add a vector of Any to
Monster table. There is also experimental support for other types besides
tables in unions, in particular structs and strings. There's no direct support
for scalars in unions, but they can be wrapped in a struct at no space cost.
### Namespaces
These will generate the corresponding namespace in C++ for all helper
code, and packages in Java. You can use `.` to specify nested namespaces /
packages.
### Includes
You can include other schemas files in your current one, e.g.:
include "mydefinitions.fbs";
This makes it easier to refer to types defined elsewhere. `include`
automatically ensures each file is parsed just once, even when referred to
more than once.
When using the `flatc` compiler to generate code for schema definitions,
only definitions in the current file will be generated, not those from the
included files (those you still generate separately).
### Root type
This declares what you consider to be the root table of the serialized
data. This is particularly important for parsing JSON data, which doesn't
include object type information.
### File identification and extension
Typically, a FlatBuffer binary buffer is not self-describing, i.e. it
needs you to know its schema to parse it correctly. But if you
want to use a FlatBuffer as a file format, it would be convenient
to be able to have a "magic number" in there, like most file formats
have, to be able to do a sanity check to see if you're reading the
kind of file you're expecting.
Now, you can always prefix a FlatBuffer with your own file header,
but FlatBuffers has a built-in way to add an identifier to a
FlatBuffer that takes up minimal space, and keeps the buffer
compatible with buffers that don't have such an identifier.
You can specify in a schema, similar to `root_type`, that you intend
for this type of FlatBuffer to be used as a file format:
file_identifier "MYFI";
Identifiers must always be exactly 4 characters long. These 4 characters
will end up as bytes at offsets 4-7 (inclusive) in the buffer.
For any schema that has such an identifier, `flatc` will automatically
add the identifier to any binaries it generates (with `-b`),
and generated calls like `FinishMonsterBuffer` also add the identifier.
If you have specified an identifier and wish to generate a buffer
without one, you can always still do so by calling
`FlatBufferBuilder::Finish` explicitly.
After loading a buffer, you can use a call like
`MonsterBufferHasIdentifier` to check if the identifier is present.
Note that this is best for open-ended uses such as files. If you simply wanted
to send one of a set of possible messages over a network for example, you'd
be better off with a union.
Additionally, by default `flatc` will output binary files as `.bin`.
This declaration in the schema will change that to whatever you want:
file_extension "ext";
### RPC interface declarations
You can declare RPC calls in a schema, that define a set of functions
that take a FlatBuffer as an argument (the request) and return a FlatBuffer
as the response (both of which must be table types):
rpc_service MonsterStorage {
Store(Monster):StoreResponse;
Retrieve(MonsterId):Monster;
}
What code this produces and how it is used depends on language and RPC system
used, there is preliminary support for GRPC through the `--grpc` code generator,
see `grpc/tests` for an example.
### Comments & documentation
May be written as in most C-based languages. Additionally, a triple
comment (`///`) on a line by itself signals that a comment is documentation
for whatever is declared on the line after it
(table/struct/field/enum/union/element), and the comment is output
in the corresponding C++ code. Multiple such lines per item are allowed.
### Attributes
Attributes may be attached to a declaration, behind a field/enum value,
or after the name of a table/struct/enum/union. These may either have
a value or not. Some attributes like `deprecated` are understood by
the compiler; user defined ones need to be declared with the attribute
declaration (like `priority` in the example above), and are
available to query if you parse the schema at runtime.
This is useful if you write your own code generators/editors etc., and
you wish to add additional information specific to your tool (such as a
help text).
Current understood attributes:
- `id: n` (on a table field): manually set the field identifier to `n`.
If you use this attribute, you must use it on ALL fields of this table,
and the numbers must be a contiguous range from 0 onwards.
Additionally, since a union type effectively adds two fields, its
id must be that of the second field (the first field is the type
field and not explicitly declared in the schema).
For example, if the last field before the union field had id 6,
the union field should have id 8, and the unions type field will
implicitly be 7.
IDs allow the fields to be placed in any order in the schema.
When a new field is added to the schema it must use the next available ID.
- `deprecated` (on a field): do not generate accessors for this field
anymore, code should stop using this data. Old data may still contain this
field, but it won't be accessible anymore by newer code. Note that if you
deprecate a field that was previous required, old code may fail to validate
new data (when using the optional verifier).
- `required` (on a non-scalar table field): this field must always be set.
By default, fields do not need to be present in the binary. This is
desirable, as it helps with forwards/backwards compatibility, and
flexibility of data structures. By specifying this attribute, you make non-
presence in an error for both reader and writer. The reading code may access
the field directly, without checking for null. If the constructing code does
not initialize this field, they will get an assert, and also the verifier
will fail on buffers that have missing required fields. Both adding and
removing this attribute may be forwards/backwards incompatible as readers
will be unable read old or new data, respectively, unless the data happens to
always have the field set.
- `force_align: size` (on a struct): force the alignment of this struct
to be something higher than what it is naturally aligned to. Causes
these structs to be aligned to that amount inside a buffer, IF that
buffer is allocated with that alignment (which is not necessarily
the case for buffers accessed directly inside a `FlatBufferBuilder`).
Note: currently not guaranteed to have an effect when used with
`--object-api`, since that may allocate objects at alignments less than
what you specify with `force_align`.
- `force_align: size` (on a vector): force the alignment of this vector to be
something different than what the element size would normally dictate.
Note: Now only work for generated C++ code.
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
meaning that any unsigned value N specified in the schema will end up
representing 1<<N, or if you don't specify values at all, you'll get
the sequence 1, 2, 4, 8, ...
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
(which must be a vector of ubyte) contains flatbuffer data, for which the
root type is given by `table_name`. The generated code will then produce
a convenient accessor for the nested FlatBuffer.
- `flexbuffer` (on a field): this indicates that the field
(which must be a vector of ubyte) contains flexbuffer data. The generated
code will then produce a convenient accessor for the FlexBuffer root.
- `key` (on a field): this field is meant to be used as a key when sorting
a vector of the type of table it sits in. Can be used for in-place
binary search.
- `hash` (on a field). This is an (un)signed 32/64 bit integer field, whose
value during JSON parsing is allowed to be a string, which will then be
stored as its hash. The value of attribute is the hashing algorithm to
use, one of `fnv1_32` `fnv1_64` `fnv1a_32` `fnv1a_64`.
- `original_order` (on a table): since elements in a table do not need
to be stored in any particular order, they are often optimized for
space by sorting them to size. This attribute stops that from happening.
There should generally not be any reason to use this flag.
- 'native_*'. Several attributes have been added to support the [C++ object
Based API](@ref flatbuffers_cpp_object_based_api). All such attributes
are prefixed with the term "native_".
## JSON Parsing
The same parser that parses the schema declarations above is also able
to parse JSON objects that conform to this schema. So, unlike other JSON
parsers, this parser is strongly typed, and parses directly into a FlatBuffer
(see the compiler documentation on how to do this from the command line, or
the C++ documentation on how to do this at runtime).
Besides needing a schema, there are a few other changes to how it parses
JSON:
- It accepts field names with and without quotes, like many JSON parsers
already do. It outputs them without quotes as well, though can be made
to output them using the `strict_json` flag.
- If a field has an enum type, the parser will recognize symbolic enum
values (with or without quotes) instead of numbers, e.g.
`field: EnumVal`. If a field is of integral type, you can still use
symbolic names, but values need to be prefixed with their type and
need to be quoted, e.g. `field: "Enum.EnumVal"`. For enums
representing flags, you may place multiple inside a string
separated by spaces to OR them, e.g.
`field: "EnumVal1 EnumVal2"` or `field: "Enum.EnumVal1 Enum.EnumVal2"`.
- Similarly, for unions, these need to specified with two fields much like
you do when serializing from code. E.g. for a field `foo`, you must
add a field `foo_type: FooOne` right before the `foo` field, where
`FooOne` would be the table out of the union you want to use.
- A field that has the value `null` (e.g. `field: null`) is intended to
have the default value for that field (thus has the same effect as if
that field wasn't specified at all).
- It has some built in conversion functions, so you can write for example
`rad(180)` where ever you'd normally write `3.14159`.
Currently supports the following functions: `rad`, `deg`, `cos`, `sin`,
`tan`, `acos`, `asin`, `atan`.
When parsing JSON, it recognizes the following escape codes in strings:
- `\n` - linefeed.
- `\t` - tab.
- `\r` - carriage return.
- `\b` - backspace.
- `\f` - form feed.
- `\"` - double quote.
- `\\` - backslash.
- `\/` - forward slash.
- `\uXXXX` - 16-bit unicode code point, converted to the equivalent UTF-8
representation.
- `\xXX` - 8-bit binary hexadecimal number XX. This is the only one that is
not in the JSON spec (see http://json.org/), but is needed to be able to
encode arbitrary binary in strings to text and back without losing
information (e.g. the byte 0xFF can't be represented in standard JSON).
It also generates these escape codes back again when generating JSON from a
binary representation.
When parsing numbers, the parser is more flexible than JSON.
A format of numeric literals is more close to the C/C++.
According to the [grammar](@ref flatbuffers_grammar), it accepts the following
numerical literals:
- An integer literal can have any number of leading zero `0` digits.
Unlike C/C++, the parser ignores a leading zero, not interpreting it as the
beginning of the octal number.
The numbers `[081, -00094]` are equal to `[81, -94]` decimal integers.
- The parser accepts unsigned and signed hexadecimal integer numbers.
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
- The format of float-point numbers is fully compatible with C/C++ format.
If a modern C++ compiler is used the parser accepts hexadecimal and special
floating-point literals as well:
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
The following conventions for floating-point numbers are used:
- The exponent suffix of hexadecimal floating-point number is mandatory.
- Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value.
Extended floating-point support was tested with:
- x64 Windows: `MSVC2015` and higher.
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section.
- For compatibility with a JSON lint tool all numeric literals of scalar
fields can be wrapped to quoted string:
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
## Guidelines
### Efficiency
FlatBuffers is all about efficiency, but to realize that efficiency you
require an efficient schema. There are usually multiple choices on
how to represent data that have vastly different size characteristics.
It is very common nowadays to represent any kind of data as dictionaries
(as in e.g. JSON), because of its flexibility and extensibility. While
it is possible to emulate this in FlatBuffers (as a vector
of tables with key and value(s)), this is a bad match for a strongly
typed system like FlatBuffers, leading to relatively large binaries.
FlatBuffer tables are more flexible than classes/structs in most systems,
since having a large number of fields only few of which are actually
used is still efficient. You should thus try to organize your data
as much as possible such that you can use tables where you might be
tempted to use a dictionary.
Similarly, strings as values should only be used when they are
truly open-ended. If you can, always use an enum instead.
FlatBuffers doesn't have inheritance, so the way to represent a set
of related data structures is a union. Unions do have a cost however,
so an alternative to a union is to have a single table that has
all the fields of all the data structures you are trying to
represent, if they are relatively similar / share many fields.
Again, this is efficient because non-present fields are cheap.
FlatBuffers supports the full range of integer sizes, so try to pick
the smallest size needed, rather than defaulting to int/long.
Remember that you can share data (refer to the same string/table
within a buffer), so factoring out repeating data into its own
data structure may be worth it.
### Style guide
Identifiers in a schema are meant to translate to many different programming
languages, so using the style of your "main" language is generally a bad idea.
For this reason, below is a suggested style guide to adhere to, to keep schemas
consistent for interoperation regardless of the target language.
Where possible, the code generators for specific languages will generate
identifiers that adhere to the language style, based on the schema identifiers.
- Table, struct, enum and rpc names (types): UpperCamelCase.
- Table and struct field names: snake_case. This is translated to lowerCamelCase
automatically for some languages, e.g. Java.
- Enum values: UpperCamelCase.
- namespaces: UpperCamelCase.
Formatting (this is less important, but still worth adhering to):
- Opening brace: on the same line as the start of the declaration.
- Spacing: Indent by 2 spaces. None around `:` for types, on both sides for `=`.
For an example, see the schema at the top of this file.
## Gotchas
### Schemas and version control
FlatBuffers relies on new field declarations being added at the end, and earlier
declarations to not be removed, but be marked deprecated when needed. We think
this is an improvement over the manual number assignment that happens in
Protocol Buffers (and which is still an option using the `id` attribute
mentioned above).
One place where this is possibly problematic however is source control. If user
A adds a field, generates new binary data with this new schema, then tries to
commit both to source control after user B already committed a new field also,
and just auto-merges the schema, the binary files are now invalid compared to
the new schema.
The solution of course is that you should not be generating binary data before
your schema changes have been committed, ensuring consistency with the rest of
the world. If this is not practical for you, use explicit field ids, which
should always generate a merge conflict if two people try to allocate the same
id.
### Schema evolution examples (tables)
Some examples to clarify what happens as you change a schema:
If we have the following original schema:
table { a:int; b:int; }
And we extend it:
table { a:int; b:int; c:int; }
This is ok. Code compiled with the old schema reading data generated with the
new one will simply ignore the presence of the new field. Code compiled with the
new schema reading old data will get the default value for `c` (which is 0
in this case, since it is not specified).
table { a:int (deprecated); b:int; }
This is also ok. Code compiled with the old schema reading newer data will now
always get the default value for `a` since it is not present. Code compiled
with the new schema now cannot read nor write `a` anymore (any existing code
that tries to do so will result in compile errors), but can still read
old data (they will ignore the field).
table { c:int; a:int; b:int; }
This is NOT ok, as this makes the schemas incompatible. Old code reading newer
data will interpret `c` as if it was `a`, and new code reading old data
accessing `a` will instead receive `b`.
table { c:int (id: 2); a:int (id: 0); b:int (id: 1); }
This is ok. If your intent was to order/group fields in a way that makes sense
semantically, you can do so using explicit id assignment. Now we are compatible
with the original schema, and the fields can be ordered in any way, as long as
we keep the sequence of ids.
table { b:int; }
NOT ok. We can only remove a field by deprecation, regardless of whether we use
explicit ids or not.
table { a:uint; b:uint; }
This is MAYBE ok, and only in the case where the type change is the same size,
like here. If old data never contained any negative numbers, this will be
safe to do.
table { a:int = 1; b:int = 2; }
Generally NOT ok. Any older data written that had 0 values were not written to
the buffer, and rely on the default value to be recreated. These will now have
those values appear to `1` and `2` instead. There may be cases in which this
is ok, but care must be taken.
table { aa:int; bb:int; }
Occasionally ok. You've renamed fields, which will break all code (and JSON
files!) that use this schema, but as long as the change is obvious, this is not
incompatible with the actual binary buffers, since those only ever address
fields by id/offset.
#### Schema evolution examples (unions)
Suppose we have the following schema:
```
union Foo { A, B }
```
We can add another variant at the end.
```
union Foo { A, B, another_a: A }
```
and this will be okay. Old code will not recognize `another_a`.
However if we add `another_a` anywhere but the end, e.g.
```
union Foo { A, another_a: A, B }
```
this is not okay. When new code writes `another_a`, old code will
misinterpret it as `B` (and vice versa). However you can explicitly
set the union's "discriminant" value like so:
```
union Foo { A = 1, another_a: A = 3, B = 2 }
```
This is okay.
```
union Foo { original_a: A = 1, another_a: A = 3, B = 2 }
```
Renaming fields will break code and any saved human readable representations,
such as json files, but the binary buffers will be the same.
<br>
### Testing whether a field is present in a table
Most serialization formats (e.g. JSON or Protocol Buffers) make it very
explicit in the format whether a field is present in an object or not,
allowing you to use this as "extra" information.
FlatBuffers will not write fields that are equal to their default value,
sometimes resulting in significant space savings. However, this also means we
cannot disambiguate the meaning of non-presence as "written default value" or
"not written at all". This only applies to scalar fields since only they support
default values. Unless otherwise specified, their default is 0.
If you care about the presence of scalars, most languages support "optional
scalars." You can set `null` as the default value in the schema. `null` is a
value that's outside of all types, so we will always write if `add_field` is
called. The generated field accessor should use the local language's canonical
optional type.
Some `FlatBufferBuilder` implementations have an option called `force_defaults`
that circumvents this "not writing defaults" behavior you can then use
`IsFieldPresent` to query presence.
/
Another option that works in all languages is to wrap a scalar field in a
struct. This way it will return null if it is not present. This will be slightly
less ergonomic but structs don't take up any more space than the scalar they
represent.
[Interface Definition Language]: https://en.wikipedia.org/wiki/Interface_description_language
## Writing your own code generator.
See [our intermediate representation](@ref intermediate_representation).

View File

@@ -1,57 +0,0 @@
Platform / Language / Feature support {#flatbuffers_support}
=====================================
FlatBuffers is actively being worked on, which means that certain platform /
language / feature combinations may not be available yet.
This page tries to track those issues, to make informed decisions easier.
In general:
* Languages: language support beyond the ones created by the original
FlatBuffer authors typically depends on community contributions.
* Features: C++ was the first language supported, since our original
target was high performance game development. It thus has the richest
feature set, and is likely most robust. Other languages are catching up
however.
* Platforms: All language implementations are typically portable to most
platforms, unless where noted otherwise.
NOTE: this table is a start, it needs to be extended.
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
------------------------------ | ------ | ----- | -------- | ----- | ------ | ----- | --- | ------ | --- | ------- | ------- | ------ | ------
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | Yes
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | Yes | No | No | No
Optional Scalars | Yes | Yes | Yes | No | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | ?
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | Great
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
Primary authors (github) | aard | aard | ev/js/df | rw | rw | ew/ev | kr | mik | ch | df | aard | rw/cn | mi/mz
Above | Github username
----- | -----------------------------
aard | aardappel (previously: gwvo)
ch | chobie
cn | caspern
df | dnfield
ev | evolutional
ew | evanw
js | jonsimantov
kr | krojew
mi | mustiikhalil
mik | mikkelfj
mz | mzaks
rw | rw
<br>

Some files were not shown because too many files have changed in this diff Show More