Compare commits

...

111 Commits

Author SHA1 Message Date
Derek Bailey
af9ceabeef FlatBuffers Version 23.1.4 (#7758) 2023-01-04 15:22:46 -08:00
Michael Le
3b2eb77595 Fix go.mod name (#7756) 2023-01-04 09:27:44 -08:00
Michael Le
6420fa5c88 [Go]Add go.mod (#7720)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2023-01-03 20:56:11 -08:00
Robin Giese
01589630ba Fix "'flatbuffers::FieldDef* field' shadows a parameter" (#7740) 2023-01-03 20:00:54 -08:00
RishabhDeep Singh
e0d68bdda2 Add link to building guide (#7733) 2022-12-22 14:06:57 -08:00
James Kuszmaul
e43a80c322 [TS] Fix getFullyQualifiedName codegen for typescript (#7730)
#7451 caused getFullyQualifiedName to return a name with underscores,
not periods. Because the fully qualified name is a property of
FlatBuffers, not the language being codegen'd for, it should use
periods. Fixes #7564.

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-22 20:59:40 +00:00
RishabhDeep Singh
449d5649d6 Fixed test cases (#7732)
* Fix Cannot find symbol and test case

* Add generated tests

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-22 20:51:39 +00:00
Michael Le
96d438df47 Perform nil check on string fields when packing (#7719)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-22 20:28:00 +00:00
engedy
4e396d47bc Add CI step to build with -DFLATBUFFERS_NO_FILE_TESTS. (#7729)
* Add CI step to build with -DFLATBUFFERS_NO_FILE_TESTS

* Fix cmake syntax

* Further fix cmake argumetns

* Add workaround for unused-parameter.

* Remove build matrix

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-22 08:48:48 -08:00
engedy
b47ba1d5ff Add include guards around DoNotRequireEofTest (#7728)
Guard DoNotRequireEofTest against -Wunused-function on platforms without file tests.
2022-12-21 14:59:34 -08:00
Casper
a078130c87 Fix Rust codegen escaping field in tables. (#7659)
* Fix Rust codegen escaping  field in tables.

* other gencode

* gencode

* removed a debug print

* regen code

Co-authored-by: Casper Neo <cneo@google.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-15 06:04:57 +00:00
Saman
9ed76559df Add clang-tidy, fix some bugpron problems. (#7708)
* Add clang-tidy, fix some bugpron problems.

* Fix more issues

* Fix some more issues :))

* Minimal pr to just add clang-tidy

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-14 21:58:55 -08:00
mogemimi
9927747d4e [C++] Fix clang -Wnewline-eof warning (#7711)
* Fix clang -Wnewline-eof warning

* Enable -Wnewline-eof warning

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-14 21:35:54 -08:00
Wen Sun
52d1b77941 Add CI job to build linux and run unit test on s390x (#7707)
* create job to build linux and run unit test on s390x

* update

* update

* update

* update

* update

* print out machine type

* create regression test to build a big endian arch and run unit tests daily

* rename and schedule run on pr merged and on request

* udpate

Co-authored-by: Wen Sun <sunwen@google.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-14 14:56:31 -08:00
Jared Junyoung Lim
40aa964057 Add Ref.AsStringBytes to flatbuffers.flexbuffers Python API (#7713)
* Add Ref.AsStringBytes to flatbuffers.flexbuffers Python API

* Append Bytes to AsStringBytes return value

Co-authored-by: Jared Junyoung Lim <jaredlim@google.com>
2022-12-14 14:42:56 -08:00
Michael Le
e1a2f688e0 [Go] Fix bug where bytes wasn't being imported when using --gen-onefile flag (#7706)
* Fix bug one file import bug

* Create reset import function and add braces
2022-12-12 23:06:48 -08:00
Saman
c0797b22ae fix clang format plus implicit cast error. (#7704) 2022-12-12 21:22:24 -08:00
Maxim Zaks
97ee210826 Fix a bug where a floating point number was cast to int and the value was stored incorrectly because of low byte width. (#7703)
Reported in https://github.com/google/flatbuffers/issues/7690
2022-12-12 21:20:26 -08:00
Max Burke
3be296ec8a [Rust] Restore public visibility of previously-public fields (#7700)
* Restore public visibility of previously-public fields

* code review feedback
2022-12-08 18:20:14 -05:00
Derek Bailey
acf39ff056 FlatBuffers Version 22.12.06 (#7702) 2022-12-06 22:54:49 -08:00
Derek Bailey
0e79e56427 inline initialize byte_width 2022-12-06 22:18:11 -08:00
郭浩伟
aadc4cb8be fix: byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3) implicit conversion loses integer precision: 'unsigned int' to 'uint8_t' (aka 'unsigned char') [-Werror,-Wimplicit-int-conversion] (#7697)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-06 21:19:54 -08:00
Wen Sun
b5ebd3fd78 [C++] Update to address comparator failure in big endian (#7681)
* update unit test and generated file to test is extra endianswap can help resolve issue

* remove EndianScalar wrapper from Get method

* remove endianscalar wrapper

* update

* update

* use Array instead

* clang format

* address error

* clang

* update

* manually generate

* Move Nim to completed language

* Add swift link

* address comments

* update unit test

* address comment

* address comment

* regenerate file

* use auto instead of size_t

* use uint32_t instead

* update

* format

* delete extra whitespace

Co-authored-by: Wen Sun <sunwen@google.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-06 14:02:16 -08:00
Michael Mickelson
11394575bc Fix "Download Doxygen" URL (#7699) 2022-12-06 14:01:12 -08:00
James Kuszmaul
5b7b36e8be Upgrade rules_go for Bazel 7.0 support (#7691)
Fixes: #7664 (hopefully)

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-12-05 16:56:02 -08:00
RishabhDeep Singh
c0230d839b Refactor src/idl_gen_cpp.cpp (#7693)
* Refactor for loops and simplify code

* Refactor for loops and simplify code

* Fix for loop and reformat

* reformat code
2022-12-06 00:43:38 +00:00
RishabhDeep Singh
a8d49f2972 Add LICENSE.txt to python (#7692)
* Add LICENSE.txt to python

* Remove LICENSE.txt from python path and used the root LICENSE.txt file
2022-12-05 16:37:21 -08:00
Derek Bailey
416c6020eb Add swift link 2022-12-02 20:52:20 -08:00
Derek Bailey
6d95867a8f Move Nim to completed language 2022-12-02 20:49:03 -08:00
Derek Bailey
2eaf790638 Fix confrom failure for nullptr dereference. (#7688) 2022-12-01 20:21:48 -08:00
Derek Bailey
3b2ced0131 Update missing C# namespace to Google.FlatBuffers 2022-12-01 20:04:49 -08:00
Michael Le
00af4e23b3 Remove --gen-name-strings flag from cmake command for generating union_vector_generated.h (#7684)
* Sync make outputs with master

* Remove --gen-name-string flag from CMAKE
2022-11-30 20:57:06 -08:00
Sergei Trofimovich
7e00b754f0 tests/reflection_test.h: add missing <stdint.h> include (#7680)
Without the change build fails on weekly `gcc-13` snapshots as:

    In file included from /build/flatbuffers/tests/reflection_test.cpp:1:
    tests/reflection_test.h:9:57: error: 'uint8_t' has not been declared
        9 | void ReflectionTest(const std::string& tests_data_path, uint8_t *flatbuf, size_t length);
          |                                                         ^~~~~~~
2022-11-30 18:47:10 -08:00
Louis Laugesen
cf89d1e756 Fix PHP byte validation and reenable builds (#7670)
* Fix PHP byte validation and reenable builds

* Use checkout@v3

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-29 08:12:28 -08:00
sssooonnnggg
ad6054c600 chore: emit more reasonable error message when using incomplete type in struct (#7678)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-29 04:59:53 +00:00
Michael Le
c3a01c7228 Use FinshedBytes() in go-echo example instead of manually encoding offset (#7660)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-29 02:29:48 +00:00
Saman
533f75d91b Fix java import wild card (#7672)
* Fix java import wild card

* fix java include

* Fix some import problems

* clang-format

* Sort imports

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-28 17:27:55 -08:00
Derek Bailey
fcab80f1bb build.yml: MacOs Build Inplace (#7677)
* `build.yml`: MacOs Build Inplace

* Update build.yml
2022-11-28 16:38:56 -08:00
Derek Bailey
5d2d0b92b1 build.yml Update dependencies (#7674)
* `build.yml` Update dependencies

* Update build.yml

* Update build.yml

* `build.yml`: Use macos-11

* Update build.yml
2022-11-28 15:34:32 -08:00
Derek Bailey
ae6662374d add buildkite badge 2022-11-23 13:11:56 -08:00
Casper
7b6c9f4a3c Rurel (#7663)
* Update release script to update Rust version (it still needs to be published after)

* Also update rust while I'm at it

Co-authored-by: Casper Neo <cneo@google.com>
2022-11-23 12:03:54 -08:00
Derek Bailey
5a42b2c76c Specify min android SDK version of 14 2022-11-23 11:54:36 -08:00
Derek Bailey
8f625561d0 FlatBuffers Version 22.11.23 (#7662) 2022-11-23 11:32:19 -08:00
Derek Bailey
9d2c04d629 FlatBuffers Version 22.11.22 2022-11-22 14:40:01 -08:00
Michael Le
e000458bb1 Add --go-module-name flag to support generating Go module compatible code (#7651)
* Add --go-module-name flag to support generating code for go modules

* Rename echo example folder

* Grammar

* Update readme for go-echo example

* Update readme for go-echo example

* Re-enable go modules after test is done
2022-11-22 14:28:01 -08:00
Michael Le
60975d6f7e Add key lookup support for tables in Go (#7644)
* Add support for key lookup for tables in Go

* Run clang format

* Run go fmt on tests

* Remove TODO in tests

* Update LookupByKey API

* Update LookupByKey API

* Don't use resolvePointer in expectEq

* Use generated getters instead of reading values directly from buffer

* Fix typo

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-22 14:08:19 -08:00
Saman
1cba8b2b49 Fix go generator undefined Package name, also throwing exception (#7632)
* Fix go generator undefined Package, also throw exception in specific examples.

* Add test for go generator import problem

* Add new version of generated go file. Fix conflict.

* Add executable permission to generate_code.py script.

* Improve test quality, remove unwanted generated files, better naming

* Fix comments

* clang format

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-22 13:21:25 -08:00
TJKoury
eead6c6219 updated method call (#7642) 2022-11-22 13:01:32 -08:00
Alex Ames
bb9b9dad5f Fixed the BytesConsumed function, which was pointing slightly ahead. (#7657)
The BytesConsumed function uses the `cursor_` to determine how many
bytes have been consumed by the parser, in case the user of the Parser
object wants to step over the parsed flatbuffer that is embedded in some
larger string. However, the `cursor_` is always one token ahead, so that
it can determine how to consume it. It points at the token that is about
to be consumed, which is ahead of the last byte consumed.

For example, if you had a string containing these two json objects and
parsed them...

    "{\"key\":\"value\"},{\"key\":\"value\"}"

...then the `cursor_` would be pointing at the comma between the two
tables. If you were to hold a pointer to the beginning of the string and
add `BytesConsumed()` to it like so:

    const char* json = // ...
    parser.ParseJson(json);
    json += parser.BytesConsumed();

then the pointer would skip over the comma, which is not the expected
behavior. It should only consume the table itself.

The solution is simple: Just hold onto a previous cursor location and
use that for the `BytesConsumed()` call. The previous cursor location
just needs to be set to the cursor_ location each time the cursor_ is
about to be updated. This will result in `BytesConsumed()` returning
the correct number of bytes without the off-by-one-token error.

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-22 20:11:14 +00:00
tira-misu
ade9e19be0 [C#] Fix collision of member if union name is "Value" (#7648)
* Fix C/C++ Create<Type>Direct with sorted vectors

If a struct has a key the vector has to be sorted. To sort the vector
you can't use "const".

* Changes due to code review

* Improve code readability

* Add generate of JSON schema to string to lib

* option indent_step is supported

* Remove unused variables

* Fix break in test

* Fix style to be consistent with rest of the code

* [TS] Fix reserved words as arguments (#6955)

* [TS] Fix generation of reserved words in object api (#7106)

* [TS] Fix generation of object api

* [TS] Fix MakeCamel -> ConvertCase

* [C#] Fix collision of field name and type name

* [TS] Add test for struct of struct of struct

* Update generated files

* Add missing files

* [TS] Fix query of null/undefined fields in object api

* [C#] Fix collision of member if enum name is "Value"

* Fix due to style guide

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-22 20:00:13 +00:00
Wen Sun
eb1abb51ea Add support for using array of scalar as key field in Cpp (#7623)
* add support for using array of scalar as key field

* update cmakelist and test.cpp to include the tests

* update bazel rule

* address comments

* clang format

* delete comment

* delete comment

* address the rest of the commnets

* address comments

* update naming in test file

* format build file

* buildifier

* make keycomparelessthan call keycomparewithvalue

* update to use flatbuffer array instead of raw pointer

* clang

* format

* revert format

* revert format

* update

* run generate_code.py

* run code generator

* revert changes by generate_code.py

* fist run make flatc and then run generate_code.py

Co-authored-by: Wen Sun <sunwen@google.com>
2022-11-18 11:04:46 -08:00
Saman
1fa6091000 Fix schema to binary test, when build and run from all directories. specially when add to other projects. (#7650) 2022-11-17 20:24:48 -08:00
tira-misu
634c2ee7e3 Put documentation to bfbs if it is not empty (#7649)
* Fix C/C++ Create<Type>Direct with sorted vectors

If a struct has a key the vector has to be sorted. To sort the vector
you can't use "const".

* Changes due to code review

* Improve code readability

* Add generate of JSON schema to string to lib

* option indent_step is supported

* Remove unused variables

* Fix break in test

* Fix style to be consistent with rest of the code

* [TS] Fix reserved words as arguments (#6955)

* [TS] Fix generation of reserved words in object api (#7106)

* [TS] Fix generation of object api

* [TS] Fix MakeCamel -> ConvertCase

* [C#] Fix collision of field name and type name

* [TS] Add test for struct of struct of struct

* Update generated files

* Add missing files

* [TS] Fix query of null/undefined fields in object api

* Put documentation to bfbs if it is not empty

* Fix monster test bfbs reference files

* Fix generated monster test files

Why they are different when generating it with linux and windows executable?
2022-11-17 15:55:42 -08:00
Derek Bailey
6f895f54c2 Add _deps/ to gitignore 2022-11-13 12:00:07 -08:00
Gh0u1L5
41d6903294 [Go] Fix GenNativeUnionUnPack for imported union type. (#7579)
* Fix GenNativeUnionUnPack for imported union type.

* Update test results.

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-13 11:52:02 -08:00
Saman
7b038e3277 Fix import problem in dart generated files. (fixes #7609). (#7621)
* Fix import problem in dart generated files. (fixes #7609).

* Fix naming.

* Fix minor changes in generated files.

* Add some tests. Fix minor problems.

* Fix minor format problem plus import alias issue.

* Minor fix in dart code generator, remove java from examples

* remove java and go generated files

* Fix dart tests.

* Fix spell problem.

* Remove excessive tests :))

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-13 19:21:57 +00:00
mr-swifter
74756e5d1b [swift] fix broken swift test build (#7633) (#7634)
* [swift] fix broken swift test build (#7633)

* [swift] fix unused variable (#7633)

* [swift] update generated code (#7633)

* [swift] add binary & json test for nan, inf, -inf for swift (#7633)

* [swift] use just '.infinity' instead of '+.infinity' (#7633)

* [swift] remove commented code (#7633)

Co-authored-by: Derek Bailey <derekbailey@google.com>
Co-authored-by: mustiikhalil <26250654+mustiikhalil@users.noreply.github.com>
2022-11-11 18:36:47 +01:00
RishabhDeep Singh
879622fc57 Fixes #7345 to add the option to minify enums (#7566)
* Added cpp minified enums

* Update generated files

* remove initializer and fix comma

* Fix .gitignore

* Fix comma

* Add tests for cpp minify enums
2022-11-11 04:47:28 +00:00
M. Şamil Ateşoğlu
83e7a98f69 [C++] Minireflect: Add option to indent when converting table to string (#7602)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-11 02:57:29 +00:00
Alex-Ratcliffe
f20b0a45b3 Add comparison operator to python objects under --gen-compare option (#7610)
* Add comparison operator to python code generator

* Missing semi-colon

* Regenerate test examples

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-11 02:47:53 +00:00
Rudi Heitbaum
207708efef [CMake]: only warn when the working directory in a git worktree (#7562)
Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>

Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-11 02:21:38 +00:00
laurentsimon
225578a8b3 Temporary fix for SLSA generators (#7636)
* Temporary fix for SLSA generators

Sigstore made a breaking change as part of their recent GA announcement. We need a temporary fix to avoid builder failure (see slsa-framework/slsa-github-generator#1163)

/cc @asraa

* Update build.yml
2022-11-10 20:09:01 -06:00
mustiikhalil
459e8acc37 Uses swift build command directly in the CI (#7635) 2022-11-10 14:16:42 -08:00
James Kuszmaul
8aa8b9139e Fix handling of +/-inf defaults in TS/rust/go/dart codegen (#7588)
+/-inf were not being handled, and so invalid typescript was being
generated when a float/double had an infinite default value. NaN was
being handled correctly.

Co-authored-by: Derek Bailey <derekbailey@google.com>
Co-authored-by: Casper <casperneo@uchicago.edu>
2022-11-08 10:59:46 -08:00
Michael Le
001adf782d Add support for parsing proto map fields (#7613)
* Add support for proto 3 map to fbs gen

* Run clang-format

* Update proto golden test

* Rename variables

* Remove iostream

* Remove iostream

* Run clang format

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-08 10:51:24 -08:00
Ben Beasley
dbc58ab77c Fix help output for --gen-includes (#7611)
Fixes the --help output documenting the deprecated --gen-includes
option, in which the option name contained a typo (--gen-inclues).
2022-11-08 18:16:17 +00:00
Ben Beasley
2facfeec7e Fix missing spaces in flatc help text (#7612)
* Fix error in --json-nested-bytes help text

Correct “bytesin” to “bytes in”

* Fix missing space in --no-leak-private-annotation help text
2022-11-08 17:59:48 +00:00
刘帅
4de2814c7b Fix: arduino platform build (#7625) 2022-11-08 09:53:53 -08:00
Valeriy Van
37b1acdaff Fix current official name of macOS (#7627)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-11-08 09:49:27 -08:00
Even Rouault
a22434e2a1 Add missing #include <algorithm> for std::min/std::max uses, and #include <limits> for std::numeric_limits<> (#7624) 2022-11-08 09:36:35 -08:00
Casper
214cc94681 Bump Rust version to 22.10.26 before publication (#7622) 2022-11-03 16:24:00 +00:00
Alex Ames
a4ff275d9b Added option to not requires an EoF token when parsing JSON (#7620)
Previously when parsing a JSON representation of a Flatbuffer, the
parser required that the input string contain one and only one root
table. This change adds a flag that removes that requirement, so that
if a Flatbuffer table is embedded in some larger string the parser will
simply stop parsing once it reaches the end of the root table, and does
not validate that it has reached the end of the string.

This change also adds a BytesConsumed function, which returns the number
of bytes the parser consumed. This is useful if the table embedded in
some larger string that is being parsed, and that outer parser needs to
know how many bytes the table was so that it can step over it.
2022-11-03 11:57:46 -04:00
inaryart
15f32c6907 python: object generation prefix and suffix (#7565)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-29 00:37:27 +00:00
Michael Le
051afd8825 Add CreateSharedString to python builder (#7608)
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-29 00:28:35 +00:00
Alejandro Ramallo
728c033ad6 Add check for presence of realpath to CMakeLists.txt to support more platforms (#7603)
* add automatic check for realpath in CMakeLists

* added win32 check

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-29 00:23:36 +00:00
Michael Le
4c514483d8 Update DartTest.sh golden files (#7606) 2022-10-29 00:15:14 +00:00
Bulent Vural
c2d9c20803 [TS] Add support for fixed length arrays on Typescript (#5864) (#7021) (#7581)
* [TS] Add support for fixed length arrays on Typescript (#5864) (#7021)

    * Typescript / Javascript don't have fixed arrays but it is important to support these languages for compatibility.

    * Generated TS code checks the length of the given array and do truncating / padding to conform to the schema.

    * Supports the both standard API and Object Based API.

    * Added a test.

    Co-authored-by: Mehmet Baker <mehmet.baker@zerodensity.tv>
    Signed-off-by: Bulent Vural <bulent.vural@zerodensity.tv>

Signed-off-by: Bülent Vural <bulent.vural@zerodensity.tv>

* Formatting & readability fixes on idl_gen_ts.cpp

Signed-off-by: Bülent Vural <bulent.vural@zerodensity.tv>

* Added array_test_complex.bfbs

Signed-off-by: Bülent Vural <bulent.vural@zerodensity.tv>

* TS arrays_test_complex: Remove bfbs and use  fbs directly

Signed-off-by: Bülent Vural <bulent.vural@zerodensity.tv>

Signed-off-by: Bülent Vural <bulent.vural@zerodensity.tv>
2022-10-28 17:00:24 -07:00
Derek Bailey
e34ae4c6b6 build.yml: Fix missing 'v' in version 2022-10-27 16:14:26 -07:00
Derek Bailey
e54536127c build.yml Update to Kotlin Wrapper 1.0.5 2022-10-27 13:55:41 -07:00
Derek Bailey
49d9f941c0 release.yml Use env var for passphrase 2022-10-26 22:50:05 -07:00
Derek Bailey
cefc21c1f9 release.yml Add GPG key for Maven 2022-10-26 22:37:11 -07:00
Derek Bailey
3e64fa7246 release.yml: Add Maven Steps 2022-10-26 22:27:20 -07:00
Derek Bailey
b15f3c57ea release_yml Use new dotnet version 2022-10-26 17:15:51 -07:00
Derek Bailey
ff802c6802 release.yml Use NuGet Key directly 2022-10-26 17:05:08 -07:00
Derek Bailey
b401957d5f release.yml Changed Push to follow examples 2022-10-26 17:01:11 -07:00
Derek Bailey
8c8151f8f9 release.yml Fix nuget push command 2022-10-26 16:41:17 -07:00
Derek Bailey
ebb7c203d3 release.yml Add Nuget support 2022-10-26 16:36:35 -07:00
Derek Bailey
203241ed32 FlatBuffers Version 22.10.26 (#7607) 2022-10-26 16:02:38 -07:00
Derek Bailey
ac485609c4 setup.py: Define version directly
Define the version directly instead of loading from an environment variable and writing to a file.
2022-10-26 15:31:02 -07:00
Derek Bailey
de5b85aa66 release.yml: Switch to python directory 2022-10-26 15:29:02 -07:00
Derek Bailey
de3df2d88b release.yml: Add publishing to PyPi 2022-10-26 15:17:21 -07:00
Joshua Smith
043a24f2e4 [Python] Fixed the issue with nested unions relying on InitFromBuf. (#7576)
* feat: Fixed the issue with nested unions relying on InitFromBuf.
Problem: Issue #7569
Nested Unions were broken with the introduction of parsing buffers with an initial encoding offset.

Fix:
Revert the InitFromBuf method to the previous version and introduction of InitFromPackedBuf that allows
users to read types from packed buffers applying the offset automatically.

Test:
Added in TestNestedUnionTables to test the encoding and decoding ability using a nested table with a
union field.

* fix: Uncommented generate code command
2022-10-26 14:56:52 -07:00
Derek Bailey
5a48b0d7d6 release.yml: Typo 2022-10-26 00:40:43 -07:00
Derek Bailey
ce307556fb release.yml: Remove npm ci
This command [was suggested](https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry) in the github docs, but not in our release steps.
2022-10-26 00:35:11 -07:00
Derek Bailey
cb616e27cb Create release.yml (#7605)
Create a new `release.yml` for defining automatic publishing to package managers on releases.

Adds the NPM publishing steps as it is the most straightforward.
2022-10-26 00:30:16 -07:00
Derek Bailey
a54ca1e759 FlatBuffers Version 22.10.25 (#7604) 2022-10-26 00:03:49 -07:00
ArnaudD-FR
5b3fadcc16 [vector] Allow to iterate with mutables (#7586)
Co-authored-by: ArnaudD-FR <arnaud.desmier@gmail.com>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-21 12:10:18 -07:00
Dan Lapid
872a497464 [Nim] Bfbs Nim Generator (#7534)
* Bfbs Nim Generator

* Remove commented out tests

* add missing line to idl.h

* Commit python reflection changes

* Commit python reflection changes and move tests

* Remove default string addition

* Move tests to python file

* Fix element size check when element is table

* remove whitespace changes

* add element_type docs and commit further to namer and remove kkeep

* Bfbs Nim Generator

* Remove commented out tests

* add missing line to idl.h

* Commit python reflection changes

* Commit python reflection changes and move tests

* Remove default string addition

* Move tests to python file

* Fix element size check when element is table

* remove whitespace changes

* add element_type docs and commit further to namer and remove kkeep

* remove unused variables

* added tests to ci

* added tests to ci

* fixes

* Added reflection type Field, Variable to namer

* Moved reflection namer impl to bfbsnamer

* Remove whitespace at end of line

* Added nim to generated code

* Revert whitespace removal

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-21 14:30:04 -04:00
Dominic Battre
e301702964 Make type conversions explicit. (#7595)
As Java does not support unsigned integer types, the value types
are "rounded up" (an uint32 is represented as a long) but persisted
correctly (an uint32 is persisted as 4 bytes).

This CL makes a cast operation explicit so that the compiler
does not throw warning messages.

Co-authored-by: Dominic Battre <battre@chromium.org>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-21 09:09:28 -07:00
Dominic Battre
f7b734438d Fix LongEnum definitions (#7596)
The MyGame/Example/LongEnum.java class did not compile because
Java expects an "L" suffix for literals of type long.

This CL fixes the code generation to include such a suffix.

Co-authored-by: Dominic Battre <battre@chromium.org>
2022-10-20 18:15:00 -07:00
Dan Lapid
5792623df4 Rust fix compilation for no_std targets #2 (#7553)
* Fix nightly no_std

* Fix nightly no_std
2022-10-19 09:14:41 -04:00
Casper
0edb275285 Update Rust version (#7574)
Co-authored-by: Casper Neo <cneo@google.com>
2022-10-18 20:37:12 +00:00
Dominic Battre
acc6a20d39 tests/test.cpp contains a couple of tests that are only executed (#7571)
on a subset of platforms. The test calls are guarded via #ifndef
FLATBUFFERS_NO_FILE_TEST.

Embedders of flatbuffers that rely on -Werror,-Wunused-function
compiler flags (like chromium) complain about the exsitence of these
tests in the anonymous namespace.

This CL guards the test definitions as well (not just the test
calls).

Co-authored-by: Dominic Battre <battre@chromium.org>
Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-10-18 12:37:06 -07:00
Casper
04cd037ba2 Fix #7580 by documenting union schema evolution rules (#7585)
Co-authored-by: Casper Neo <cneo@google.com>
2022-10-17 17:49:28 -04:00
Casper
e1c5db988a Turn on clippy for Rust and fix lints for non-generated code (#7575)
Co-authored-by: Casper Neo <cneo@google.com>
2022-10-10 21:26:35 -04:00
Piotr Dziwiński
b80142b901 Update documentation to mention enum value attributes (#7570) 2022-10-08 19:52:38 -04:00
Piotr Dziwiński
54418f371b Add support for metadata attributes for enum values (#7567) (#7568)
* Add support for metadata attributes for enum values (#7567)

* Fix path lookup in flatc test

* Try a fix for Windows paths

* Convert path to string to fix Windows error
2022-10-06 20:18:00 -04:00
Derek Bailey
c92e78a9f8 FlatBuffers Version 22.9.29 (#7557) 2022-09-29 22:12:07 -07:00
Björn Harrtell
d243b904cc [TS] Make strict compliant and improve typings (#7549)
* [TS] Make strict compliant and improve typings

* clang-format

* Code gen harmonize

Co-authored-by: Derek Bailey <derekbailey@google.com>
2022-09-29 15:03:35 -07:00
Raphael Taylor-Davies
374f8fb5fb Rust soundness fixes (#7518)
* Rust soundness fixes

* Second pass

* Make init_from_table unsafe

* Remove SafeSliceAccess

* Clippy

* Remove create_vector_of_strings

* More clippy

* Remove deprecated root type accessors

* More soundness fixes

* Fix EndianScalar for bool

* Add TriviallyTransmutable

* Add debug assertions

* Review comments

* Review feedback
2022-09-29 09:58:49 -04:00
mustiikhalil
dadbff5714 Moves swift package to root of repository so it can be used directly … (#7548)
* Moves swift package to root of repository so it can be used directly from the main repo

Fixing paths for swift directory

* Update swift readme
2022-09-27 14:32:05 -07:00
585 changed files with 25082 additions and 10043 deletions

347
.clang-tidy Normal file
View File

@@ -0,0 +1,347 @@
---
FormatStyle: "file"
WarningsAsErrors: "*"
HeaderFilterRegex: ".*"
Checks: "google-build-explicit-make-pair,
google-build-namespaces,
google-build-using-namespace,
google-default-arguments,
google-explicit-constructor,
google-global-names-in-headers,
google-objc-avoid-nsobject-new,
google-objc-avoid-throwing-exception,
google-objc-function-naming,
google-objc-global-variable-declaration,
google-readability-avoid-underscore-in-googletest-name,
google-readability-braces-around-statements,
google-readability-casting,
google-readability-function-size,
google-readability-namespace-comments,
google-runtime-int,
google-runtime-operator,
google-upgrade-googletest-case,
clang-analyzer-apiModeling.StdCLibraryFunctions,
clang-analyzer-apiModeling.TrustNonnull,
clang-analyzer-apiModeling.google.GTest,
clang-analyzer-apiModeling.llvm.CastValue,
clang-analyzer-apiModeling.llvm.ReturnValue,
clang-analyzer-core.CallAndMessage,
clang-analyzer-core.CallAndMessageModeling,
clang-analyzer-core.DivideZero,
clang-analyzer-core.DynamicTypePropagation,
clang-analyzer-core.NonNullParamChecker,
clang-analyzer-core.NonnilStringConstants,
clang-analyzer-core.NullDereference,
clang-analyzer-core.StackAddrEscapeBase,
clang-analyzer-core.StackAddressEscape,
clang-analyzer-core.UndefinedBinaryOperatorResult,
clang-analyzer-core.VLASize,
clang-analyzer-core.builtin.BuiltinFunctions,
clang-analyzer-core.builtin.NoReturnFunctions,
clang-analyzer-core.uninitialized.ArraySubscript,
clang-analyzer-core.uninitialized.Assign,
clang-analyzer-core.uninitialized.Branch,
clang-analyzer-core.uninitialized.CapturedBlockVariable,
clang-analyzer-core.uninitialized.UndefReturn,
clang-analyzer-cplusplus.InnerPointer,
clang-analyzer-cplusplus.Move,
clang-analyzer-cplusplus.NewDelete,
clang-analyzer-cplusplus.NewDeleteLeaks,
clang-analyzer-cplusplus.PlacementNew,
clang-analyzer-cplusplus.PureVirtualCall,
clang-analyzer-cplusplus.SelfAssignment,
clang-analyzer-cplusplus.SmartPtrModeling,
clang-analyzer-cplusplus.StringChecker,
clang-analyzer-cplusplus.VirtualCallModeling,
clang-analyzer-deadcode.DeadStores,
clang-analyzer-fuchsia.HandleChecker,
clang-analyzer-nullability.NullPassedToNonnull,
clang-analyzer-nullability.NullReturnedFromNonnull,
clang-analyzer-nullability.NullabilityBase,
clang-analyzer-nullability.NullableDereferenced,
clang-analyzer-nullability.NullablePassedToNonnull,
clang-analyzer-nullability.NullableReturnedFromNonnull,
clang-analyzer-optin.cplusplus.UninitializedObject,
clang-analyzer-optin.cplusplus.VirtualCall,
clang-analyzer-optin.mpi.MPI-Checker,
clang-analyzer-optin.osx.OSObjectCStyleCast,
clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,
clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker,
clang-analyzer-optin.performance.GCDAntipattern,
clang-analyzer-optin.performance.Padding,
clang-analyzer-optin.portability.UnixAPI,
clang-analyzer-osx.API,
clang-analyzer-osx.MIG,
clang-analyzer-osx.NSOrCFErrorDerefChecker,
clang-analyzer-osx.NumberObjectConversion,
clang-analyzer-osx.OSObjectRetainCount,
clang-analyzer-osx.ObjCProperty,
clang-analyzer-osx.SecKeychainAPI,
clang-analyzer-osx.cocoa.AtSync,
clang-analyzer-osx.cocoa.AutoreleaseWrite,
clang-analyzer-osx.cocoa.ClassRelease,
clang-analyzer-osx.cocoa.Dealloc,
clang-analyzer-osx.cocoa.IncompatibleMethodTypes,
clang-analyzer-osx.cocoa.Loops,
clang-analyzer-osx.cocoa.MissingSuperCall,
clang-analyzer-osx.cocoa.NSAutoreleasePool,
clang-analyzer-osx.cocoa.NSError,
clang-analyzer-osx.cocoa.NilArg,
clang-analyzer-osx.cocoa.NonNilReturnValue,
clang-analyzer-osx.cocoa.ObjCGenerics,
clang-analyzer-osx.cocoa.RetainCount,
clang-analyzer-osx.cocoa.RetainCountBase,
clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak,
clang-analyzer-osx.cocoa.SelfInit,
clang-analyzer-osx.cocoa.SuperDealloc,
clang-analyzer-osx.cocoa.UnusedIvars,
clang-analyzer-osx.cocoa.VariadicMethodTypes,
clang-analyzer-osx.coreFoundation.CFError,
clang-analyzer-osx.coreFoundation.CFNumber,
clang-analyzer-osx.coreFoundation.CFRetainRelease,
clang-analyzer-osx.coreFoundation.containers.OutOfBounds,
clang-analyzer-osx.coreFoundation.containers.PointerSizedValues,
clang-analyzer-security.FloatLoopCounter,
clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
clang-analyzer-security.insecureAPI.SecuritySyntaxChecker,
clang-analyzer-security.insecureAPI.UncheckedReturn,
clang-analyzer-security.insecureAPI.bcmp,
clang-analyzer-security.insecureAPI.bcopy,
clang-analyzer-security.insecureAPI.bzero,
clang-analyzer-security.insecureAPI.decodeValueOfObjCType,
clang-analyzer-security.insecureAPI.getpw,
clang-analyzer-security.insecureAPI.gets,
clang-analyzer-security.insecureAPI.mkstemp,
clang-analyzer-security.insecureAPI.mktemp,
clang-analyzer-security.insecureAPI.rand,
clang-analyzer-security.insecureAPI.strcpy,
clang-analyzer-security.insecureAPI.vfork,
clang-analyzer-unix.API,
clang-analyzer-unix.DynamicMemoryModeling,
clang-analyzer-unix.Malloc,
clang-analyzer-unix.MallocSizeof,
clang-analyzer-unix.MismatchedDeallocator,
clang-analyzer-unix.Vfork,
clang-analyzer-unix.cstring.BadSizeArg,
clang-analyzer-unix.cstring.CStringModeling,
clang-analyzer-unix.cstring.NullArg,
clang-analyzer-valist.CopyToSelf,
clang-analyzer-valist.Uninitialized,
clang-analyzer-valist.Unterminated,
clang-analyzer-valist.ValistBase,
clang-analyzer-webkit.NoUncountedMemberChecker,
clang-analyzer-webkit.RefCntblBaseVirtualDtor,
clang-analyzer-webkit.UncountedLambdaCapturesChecker,
################################################ Optional checks ################################################
#google-readability-todo,
#bugprone-argument-comment,
#bugprone-assert-side-effect,
#bugprone-bad-signal-to-kill-thread,
#bugprone-bool-pointer-implicit-conversion,
#bugprone-branch-clone,
#bugprone-copy-constructor-init,
#bugprone-dangling-handle,
#bugprone-dynamic-static-initializers,
#bugprone-easily-swappable-parameters,
#bugprone-exception-escape,
#bugprone-fold-init-type,
#bugprone-forward-declaration-namespace,
#bugprone-forwarding-reference-overload,
#bugprone-implicit-widening-of-multiplication-result,
#bugprone-inaccurate-erase,
#bugprone-incorrect-roundings,
#bugprone-infinite-loop,
#bugprone-integer-division,
#bugprone-lambda-function-name,
#bugprone-macro-parentheses,
#bugprone-macro-repeated-side-effects,
#bugprone-misplaced-operator-in-strlen-in-alloc,
#bugprone-misplaced-pointer-arithmetic-in-alloc,
#bugprone-misplaced-widening-cast,
#bugprone-move-forwarding-reference,
#bugprone-multiple-statement-macro,
#bugprone-narrowing-conversions,
#bugprone-no-escape,
#bugprone-not-null-terminated-result,
#bugprone-parent-virtual-call,
#bugprone-posix-return,
#bugprone-redundant-branch-condition,
#bugprone-reserved-identifier,
#bugprone-signal-handler,
#bugprone-signed-char-misuse,
#bugprone-sizeof-container,
#bugprone-sizeof-expression,
#bugprone-spuriously-wake-up-functions,
#bugprone-string-constructor,
#bugprone-string-integer-assignment,
#bugprone-string-literal-with-embedded-nul,
#bugprone-stringview-nullptr,
#bugprone-suspicious-enum-usage,
#bugprone-suspicious-include,
#bugprone-suspicious-memory-comparison,
#bugprone-suspicious-memset-usage,
#bugprone-suspicious-missing-comma,
#bugprone-suspicious-semicolon,
#bugprone-suspicious-string-compare,
#bugprone-swapped-arguments,
#bugprone-terminating-continue,
#bugprone-throw-keyword-missing,
#bugprone-too-small-loop-variable,
#bugprone-undefined-memory-manipulation,
#bugprone-undelegated-constructor,
#bugprone-unhandled-exception-at-new,
#bugprone-unhandled-self-assignment,
#bugprone-unused-raii,
#bugprone-unused-return-value,
#bugprone-use-after-move,
#bugprone-virtual-near-miss,
#cppcoreguidelines-avoid-c-arrays,
#cppcoreguidelines-avoid-goto,
#cppcoreguidelines-avoid-magic-numbers,
#cppcoreguidelines-avoid-non-const-global-variables,
#cppcoreguidelines-c-copy-assignment-signature,
#cppcoreguidelines-explicit-virtual-functions,
#cppcoreguidelines-init-variables,
#cppcoreguidelines-interfaces-global-init,
#cppcoreguidelines-macro-usage,
#cppcoreguidelines-narrowing-conversions,
#cppcoreguidelines-no-malloc,
#cppcoreguidelines-non-private-member-variables-in-classes,
#cppcoreguidelines-owning-memory,
#cppcoreguidelines-prefer-member-initializer,
#cppcoreguidelines-pro-bounds-array-to-pointer-decay,
#cppcoreguidelines-pro-bounds-constant-array-index,
#cppcoreguidelines-pro-bounds-pointer-arithmetic,
#cppcoreguidelines-pro-type-const-cast,
#cppcoreguidelines-pro-type-cstyle-cast,
#cppcoreguidelines-pro-type-member-init,
#cppcoreguidelines-pro-type-reinterpret-cast,
#cppcoreguidelines-pro-type-static-cast-downcast,
#cppcoreguidelines-pro-type-union-access,
#cppcoreguidelines-pro-type-vararg,
#cppcoreguidelines-slicing,
#cppcoreguidelines-special-member-functions,
#cppcoreguidelines-virtual-class-destructor,
#hicpp-avoid-c-arrays,
#hicpp-avoid-goto,
#hicpp-braces-around-statements,
#hicpp-deprecated-headers,
#hicpp-exception-baseclass,
#hicpp-explicit-conversions,
#hicpp-function-size,
#hicpp-invalid-access-moved,
#hicpp-member-init,
#hicpp-move-const-arg,
#hicpp-multiway-paths-covered,
#hicpp-named-parameter,
#hicpp-new-delete-operators,
#hicpp-no-array-decay,
#hicpp-no-assembler,
#hicpp-no-malloc,
#hicpp-noexcept-move,
#hicpp-signed-bitwise,
#hicpp-special-member-functions,
#hicpp-static-assert,
#hicpp-undelegated-constructor,
#hicpp-uppercase-literal-suffix,
#hicpp-use-auto,
#hicpp-use-emplace,
#hicpp-use-equals-default,
#hicpp-use-equals-delete,
#hicpp-use-noexcept,
#hicpp-use-nullptr,
#hicpp-use-override,
#hicpp-vararg,
#modernize-avoid-bind,
#modernize-avoid-c-arrays,
#modernize-concat-nested-namespaces,
#modernize-deprecated-headers,
#modernize-deprecated-ios-base-aliases,
#modernize-loop-convert,
#modernize-make-shared,
#modernize-make-unique,
#modernize-pass-by-value,
#modernize-raw-string-literal,
#modernize-redundant-void-arg,
#modernize-replace-auto-ptr,
#modernize-replace-disallow-copy-and-assign-macro,
#modernize-replace-random-shuffle,
#modernize-return-braced-init-list,
#modernize-shrink-to-fit,
#modernize-unary-static-assert,
#modernize-use-auto,
#modernize-use-bool-literals,
#modernize-use-default-member-init,
#modernize-use-emplace,
#modernize-use-equals-default,
#modernize-use-equals-delete,
#modernize-use-nodiscard,
#modernize-use-noexcept,
#modernize-use-nullptr,
#modernize-use-override,
#modernize-use-trailing-return-type,
#modernize-use-transparent-functors,
#modernize-use-uncaught-exceptions,
#modernize-use-using,
#performance-faster-string-find,
#performance-for-range-copy,
#performance-implicit-conversion-in-loop,
#performance-inefficient-algorithm,
#performance-inefficient-string-concatenation,
#performance-inefficient-vector-operation,
#performance-move-const-arg,
#performance-move-constructor-init,
#performance-no-automatic-move,
#performance-no-int-to-ptr,
#performance-noexcept-move-constructor,
#performance-trivially-destructible,
#performance-type-promotion-in-math-fn,
#performance-unnecessary-copy-initialization,
#performance-unnecessary-value-param,
#portability-restrict-system-includes,
#portability-simd-intrinsics,
#readability-avoid-const-params-in-decls,
#readability-braces-around-statements,
#readability-const-return-type,
#readability-container-contains,
#readability-container-data-pointer,
#readability-container-size-empty,
#readability-convert-member-functions-to-static,
#readability-delete-null-pointer,
#readability-duplicate-include,
#readability-else-after-return,
#readability-function-cognitive-complexity,
#readability-function-size,
#readability-identifier-length,
#readability-identifier-naming,
#readability-implicit-bool-conversion,
#readability-inconsistent-declaration-parameter-name,
#readability-isolate-declaration,
#readability-magic-numbers,
#readability-make-member-function-const,
#readability-misleading-indentation,
#readability-misplaced-array-index,
#readability-named-parameter,
#readability-non-const-parameter,
#readability-qualified-auto,
#readability-redundant-access-specifiers,
#readability-redundant-control-flow,
#readability-redundant-declaration,
#readability-redundant-function-ptr-dereference,
#readability-redundant-member-init,
#readability-redundant-preprocessor,
#readability-redundant-smartptr-get,
#readability-redundant-string-cstr,
#readability-redundant-string-init,
#readability-simplify-boolean-expr,
#readability-simplify-subscript-expr,
#readability-static-accessed-through-instance,
#readability-static-definition-in-anonymous-namespace,
#readability-string-compare,
#readability-suspicious-call-argument,
#readability-uniqueptr-delete-release,
#readability-uppercase-literal-suffix,
#readability-use-anyofallof
"

View File

@@ -3,7 +3,7 @@ Thank you for submitting a PR!
Please delete this standard text once you've created your own description. Please delete this standard text once you've created your own description.
If you make changes to any of the code generators (`src/idl_gen*`) be sure to If you make changes to any of the code generators (`src/idl_gen*`) be sure to
build your project, as it will generate code based on the changes. If necessary [build](https://google.github.io/flatbuffers/flatbuffers_guide_building.html) your project, as it will generate code based on the changes. If necessary
the code generation script can be directly run (`scripts/generate_code.py`), the code generation script can be directly run (`scripts/generate_code.py`),
requires Python3. This allows us to better see the effect of the PR. requires Python3. This allows us to better see the effect of the PR.

10
.github/labeler.yml vendored
View File

@@ -18,6 +18,12 @@ swift:
- tests/swift/** - tests/swift/**
- src/idl_gen_swift.cpp - src/idl_gen_swift.cpp
nim:
- '**/*.nim'
- nim/**/*
- src/idl_gen_nim.cpp
- src/bfbs_gen_nim.cpp
javascript: javascript:
- '**/*.js' - '**/*.js'
- src/idl_gen_ts.cpp - src/idl_gen_ts.cpp
@@ -61,7 +67,7 @@ rust:
- '**/*.rs' - '**/*.rs'
- rust/**/* - rust/**/*
- src/idl_gen_rust.cpp - src/idl_gen_rust.cpp
dart: dart:
- '**/*.dart' - '**/*.dart'
- src/idl_gen_dart.cpp - src/idl_gen_dart.cpp
@@ -88,4 +94,4 @@ CI:
grpc: grpc:
- grpc/**/* - grpc/**/*
- src/idl_gen_grpc.cpp - src/idl_gen_grpc.cpp

View File

@@ -27,7 +27,7 @@ jobs:
cxx: [g++-10, clang++-12] cxx: [g++-10, clang++-12]
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build - name: build
@@ -62,6 +62,16 @@ jobs:
if: matrix.cxx == 'g++-10' && startsWith(github.ref, 'refs/tags/') if: matrix.cxx == 'g++-10' && startsWith(github.ref, 'refs/tags/')
id: hash-gcc id: hash-gcc
run: echo "::set-output name=hashes::$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)" run: echo "::set-output name=hashes::$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)"
build-linux-no-file-tests:
name: Build Linux with -DFLATBUFFERS_NO_FILE_TESTS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: cmake
run: CXX=clang++-12 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_CXX_FLAGS="-DFLATBUFFERS_NO_FILE_TESTS" .
- name: build
run: make -j
build-linux-cpp-std: build-linux-cpp-std:
name: Build Linux C++ name: Build Linux C++
@@ -76,7 +86,7 @@ jobs:
- cxx: g++-10 - cxx: g++-10
std: 23 std: 23
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - name: cmake
run: > run: >
CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles"
@@ -99,7 +109,7 @@ jobs:
std: [11, 14, 17, 20, 23] std: [11, 14, 17, 20, 23]
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
@@ -124,7 +134,7 @@ jobs:
name: Build Windows 2019 name: Build Windows 2019
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
@@ -159,7 +169,7 @@ jobs:
name: Build Windows 2017 name: Build Windows 2017
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
@@ -173,7 +183,7 @@ jobs:
name: Build Windows 2015 name: Build Windows 2015
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
@@ -195,9 +205,9 @@ jobs:
#'-p:EnableSpanT=true,UnsafeByteBuffer=true' #'-p:EnableSpanT=true,UnsafeByteBuffer=true'
] ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Setup .NET Core SDK - name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1.9.0 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '3.1.x' dotnet-version: '3.1.x'
- name: Build - name: Build
@@ -219,34 +229,33 @@ jobs:
name: Build Mac (for Intel) name: Build Mac (for Intel)
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - name: cmake
run: cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_FLATC_EXECUTABLE=_build/Release/flatc -DFLATBUFFERS_STRICT_MODE=ON . run: cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build - name: build
# NOTE: we need this _build dir to not have xcodebuild's default ./build dir clash with the BUILD file. run: xcodebuild -toolchain clang -configuration Release -target flattests
run: xcodebuild -toolchain clang -configuration Release -target flattests SYMROOT=$(PWD)/_build
- name: check that the binary is x86_64 - name: check that the binary is x86_64
run: | run: |
info=$(file _build/Release/flatc) info=$(file Release/flatc)
echo $info echo $info
echo $info | grep "Mach-O 64-bit executable x86_64" echo $info | grep "Mach-O 64-bit executable x86_64"
- name: test - name: test
run: _build/Release/flattests run: Release/flattests
- name: make flatc executable - name: make flatc executable
run: | run: |
chmod +x _build/Release/flatc chmod +x Release/flatc
./_build/Release/flatc --version Release/flatc --version
- name: flatc tests - name: flatc tests
run: python3 tests/flatc/main.py --flatc ./_build/Release/flatc run: python3 tests/flatc/main.py --flatc Release/flatc
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:
name: Mac flatc binary name: Mac flatc binary
path: _build/Release/flatc path: Release/flatc
# Below if only for release. # Below if only for release.
- name: Zip file - name: Zip file
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
run: mv _build/Release/flatc . && zip MacIntel.flatc.binary.zip flatc run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc
- name: Release binary - name: Release binary
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
@@ -265,32 +274,31 @@ jobs:
name: Build Mac (universal build) name: Build Mac (universal build)
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - name: cmake
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_FLATC_EXECUTABLE=_build/Release/flatc -DFLATBUFFERS_STRICT_MODE=ON . run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build - name: build
# NOTE: we need this _build dir to not have xcodebuild's default ./build dir clash with the BUILD file. run: xcodebuild -toolchain clang -configuration Release -target flattests
run: xcodebuild -toolchain clang -configuration Release -target flattests SYMROOT=$(PWD)/_build
- name: check that the binary is "universal" - name: check that the binary is "universal"
run: | run: |
info=$(file _build/Release/flatc) info=$(file Release/flatc)
echo $info echo $info
echo $info | grep "Mach-O universal binary with 2 architectures" echo $info | grep "Mach-O universal binary with 2 architectures"
- name: test - name: test
run: _build/Release/flattests run: Release/flattests
- name: make flatc executable - name: make flatc executable
run: | run: |
chmod +x _build/Release/flatc chmod +x Release/flatc
./_build/Release/flatc --version Release/flatc --version
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:
name: Mac flatc binary name: Mac flatc binary
path: _build/Release/flatc path: Release/flatc
# Below if only for release. # Below if only for release.
- name: Zip file - name: Zip file
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
run: mv _build/Release/flatc . && zip Mac.flatc.binary.zip flatc run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc
- name: Release binary - name: Release binary
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
@@ -305,11 +313,12 @@ jobs:
name: Build Android (on Linux) name: Build Android (on Linux)
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: set up JDK 1.8 - name: set up Java
uses: actions/setup-java@v1 uses: actions/setup-java@v3
with: with:
java-version: 1.8 distribution: 'temurin'
java-version: '11'
- name: set up flatc - name: set up flatc
run: | run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
@@ -326,7 +335,7 @@ jobs:
matrix: matrix:
cxx: [g++-10, clang++-12] cxx: [g++-10, clang++-12]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
- name: Generate - name: Generate
@@ -341,7 +350,7 @@ jobs:
matrix: matrix:
cxx: [g++-10] cxx: [g++-10]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: cmake - 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 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 - name: Run benchmarks
@@ -356,7 +365,7 @@ jobs:
name: Build Java name: Build Java
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: test - name: test
working-directory: java working-directory: java
run: mvn test run: mvn test
@@ -366,11 +375,11 @@ jobs:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1 - uses: gradle/wrapper-validation-action@v1.0.5
- uses: actions/setup-java@v2 - uses: actions/setup-java@v3
with: with:
distribution: 'adopt-hotspot' distribution: 'temurin'
java-version: '11' java-version: '11'
- name: Build - name: Build
working-directory: kotlin working-directory: kotlin
@@ -381,16 +390,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- uses: actions/setup-java@v2 - uses: actions/setup-java@v3
with: with:
distribution: 'adopt-hotspot' distribution: 'temurin'
java-version: '11' java-version: '11'
- uses: gradle/wrapper-validation-action@v1 - uses: gradle/wrapper-validation-action@v1.0.5
- name: Build - name: Build
working-directory: kotlin working-directory: kotlin
# we are using docker's version of gradle # we are using docker's version of gradle
# so no need for wrapper validadation or user # so no need for wrapper validation or user
# gradlew # gradlew
run: gradle jvmMainClasses jvmTest jsTest jsBrowserTest run: gradle jvmMainClasses jvmTest jsTest jsBrowserTest
@@ -398,7 +407,7 @@ jobs:
name: Build Rust name: Build Rust
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: test - name: test
working-directory: tests working-directory: tests
run: bash RustTest.sh run: bash RustTest.sh
@@ -407,7 +416,7 @@ jobs:
name: Build Python name: Build Python
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: test - name: test
working-directory: tests working-directory: tests
run: bash PythonTest.sh run: bash PythonTest.sh
@@ -416,7 +425,7 @@ jobs:
name: Build Go name: Build Go
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: flatc - name: flatc
# FIXME: make test script not rely on 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 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
@@ -424,14 +433,30 @@ jobs:
working-directory: tests working-directory: tests
run: bash GoTest.sh run: bash GoTest.sh
build-php:
name: Build PHP
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- 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
- name: test
working-directory: tests
run: |
php phpTest.php
sh phpUnionVectorTest.sh
build-swift: build-swift:
name: Build Swift name: Build Swift
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: test - name: test
working-directory: tests/swift/tests working-directory: tests/swift/tests
run: sh SwiftTest.sh run: |
swift build --build-tests
swift test
build-swift-wasm: build-swift-wasm:
name: Build Swift Wasm name: Build Swift Wasm
@@ -439,9 +464,9 @@ jobs:
container: container:
image: ghcr.io/swiftwasm/carton:0.15.3 image: ghcr.io/swiftwasm/carton:0.15.3
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Setup Wasmer - name: Setup Wasmer
uses: wasmerio/setup-wasmer@v1 uses: wasmerio/setup-wasmer@v2
- name: Test - name: Test
working-directory: tests/swift/Wasm.tests working-directory: tests/swift/Wasm.tests
run: carton test run: carton test
@@ -450,7 +475,7 @@ jobs:
name: Build TS name: Build TS
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: flatc - name: flatc
# FIXME: make test script not rely on 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 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
@@ -466,7 +491,7 @@ jobs:
name: Build Dart name: Build Dart
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1 - uses: dart-lang/setup-dart@v1
with: with:
sdk: stable sdk: stable
@@ -477,6 +502,22 @@ jobs:
working-directory: tests working-directory: tests
run: bash DartTest.sh run: bash DartTest.sh
build-nim:
name: Build Nim
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- 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
- name: install library
working-directory: nim
run: nimble -y develop
- name: test
working-directory: tests/nim
run: python3 testnim.py
release-digests: release-digests:
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal] needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
@@ -508,7 +549,8 @@ jobs:
actions: read # To read the workflow path. actions: read # To read the workflow path.
id-token: write # To sign the provenance. id-token: write # To sign the provenance.
contents: write # To add assets to a release. contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.1
with: with:
base64-subjects: "${{ needs.release-digests.outputs.digests }}" base64-subjects: "${{ needs.release-digests.outputs.digests }}"
upload-assets: true # Optional: Upload to a new release upload-assets: true # Optional: Upload to a new release
compile-generator: true # Workaround for https://github.com/slsa-framework/slsa-github-generator/issues/1163

35
.github/workflows/extrabuild.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Build and unit tests that are more time consuming
permissions: read-all
on:
# For manual tests.
workflow_dispatch:
pull_request:
types:
- closed
schedule:
- cron: "30 20 * * *"
jobs:
build-linux-s390x:
name: Build Linux on s390x arch and run unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: uraimo/run-on-arch-action@v2
name: Run commands
id: runcmd
with:
arch: s390x
distro: ubuntu_latest
install: |
apt-get update -q -y
apt-get -y install cmake
apt-get -y install make
apt-get -y install g++
run: |
lscpu | grep Endian
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
make -j
./flattests

106
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: Release
permissions: read-all
on:
# For manual tests.
workflow_dispatch:
release:
types: [created]
jobs:
publish-npm:
name: Publish NPM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16.x'
registry-url: 'https://registry.npmjs.org'
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-pypi:
name: Publish PyPi
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./python
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install setuptools wheel twine
- name: Build
run: |
python3 setup.py sdist bdist_wheel
- name: Upload to PyPi
run: |
python3 -m twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }}
publish-nuget:
name: Publish NuGet
runs-on: windows-latest
defaults:
run:
working-directory: ./net/flatbuffers
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
- name: Build
run: |
dotnet build Google.FlatBuffers.csproj -c Release
- name: Pack
run: |
dotnet pack Google.FlatBuffers.csproj -c Release
- name: Upload to NuGet
run: |
dotnet nuget push .\bin\Release\Google.FlatBuffers.*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
publish-maven:
name: Publish Maven
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./java
steps:
- uses: actions/checkout@v3
- name: Set up Maven Central Repository
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: 'maven'
server-id: ossrh
server-username: OSSRH_USERNAME
server-password: OSSRH_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var
- name: Publish Maven
run: mvn --batch-mode clean deploy
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

1
.gitignore vendored
View File

@@ -149,4 +149,5 @@ flatbuffers.pc
**/html/** **/html/**
**/latex/** **/latex/**
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR # https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR
cmake-build-debug/
_deps/ _deps/

View File

@@ -4,7 +4,37 @@ 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 new features that should be highlighted. Minor fixes or improvements are not
necessarily listed. necessarily listed.
## 22.9.24 (Sept 24 2022) ## [23.1.4 (Jan 4 2023)](https://github.com/google/flatbuffers/releases/tag/v23.1.4)
* Major release! Just kidding, we are continuing the
[versioning scheme](https://github.com/google/flatbuffers/wiki/Versioning) of
using a date to signify releases. This results in the first release of the new
year to bump the tradition major version field.
* Go minimum version is now 1.19 (#7720) with the addition of Go modules.
* Added CI support for Big Endian regression testing (#7707).
* Fixed `getFullyQualifiedName` in typescript to return name delimited by '.'
instead of '_' (#7730).
* Fixed the versioning scheme to not include leading zeros which are not
consistently handled by every package manager. Only the last release
(12.12.06) should have suffered from this.
## [22.12.06 (Dec 06 2022)](https://github.com/google/flatbuffers/releases/tag/v22.12.06)
* Bug fixing release, no major changes.
## [22.10.25 (Oct 25 2022)](https://github.com/google/flatbuffers/releases/tag/v22.10.25)
* Added Nim language support with generator and runtime libraries (#7534).
## [22.9.29 (Sept 29 2022)](https://github.com/google/flatbuffers/releases/tag/v22.9.29)
* Rust soundness fixes to avoid the crate from bing labelled unsafe (#7518).
## [22.9.24 (Sept 24 2022)](https://github.com/google/flatbuffers/releases/tag/v22.9.24)
* 20 Major releases in a row? Nope, we switched to a new * 20 Major releases in a row? Nope, we switched to a new
[versioning scheme](https://github.com/google/flatbuffers/wiki/Versioning) [versioning scheme](https://github.com/google/flatbuffers/wiki/Versioning)
@@ -23,8 +53,8 @@ necessarily listed.
`AlignOf()` for structs (#7520). `AlignOf()` for structs (#7520).
* C# has an * C# has an
[offical Nuget package](https://www.nuget.org/packages/Google.FlatBuffers) now [official Nuget package](https://www.nuget.org/packages/Google.FlatBuffers)
(#7496). now (#7496).
## 2.0.8 (Aug 29 2022) ## 2.0.8 (Aug 29 2022)
@@ -55,4 +85,4 @@ necessarily listed.
* First binary schema generator (Lua) to generate Lua code via a .bfbs file. * First binary schema generator (Lua) to generate Lua code via a .bfbs file.
This is mostly an implementation detail of flatc internals, but will be slowly This is mostly an implementation detail of flatc internals, but will be slowly
applied to the other language generators. applied to the other language generators.

View File

@@ -1,37 +1,39 @@
set(VERSION_MAJOR 22) set(VERSION_MAJOR 23)
set(VERSION_MINOR 9) set(VERSION_MINOR 1)
set(VERSION_PATCH 24) set(VERSION_PATCH 4)
set(VERSION_COMMIT 0) set(VERSION_COMMIT 0)
find_program(GIT git) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
if(GIT AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") find_program(GIT git)
execute_process( if(GIT)
execute_process(
COMMAND ${GIT} describe --tags COMMAND ${GIT} describe --tags
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE GIT_DESCRIBE_RESULT RESULT_VARIABLE GIT_DESCRIBE_RESULT
) )
if(GIT_DESCRIBE_RESULT EQUAL 0) if(GIT_DESCRIBE_RESULT EQUAL 0)
# Test if the most recent Git tag matches the pattern "v<major>.<minor>.<patch>*" # Test if the most recent Git tag matches the pattern "v<major>.<minor>.<patch>*"
if(GIT_DESCRIBE_DIRTY MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+.*") if(GIT_DESCRIBE_DIRTY MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+.*")
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}") string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}") string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}") string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}") string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
# If the tag points to the commit, then only the tag is shown in "git describe" # If the tag points to the commit, then only the tag is shown in "git describe"
if(VERSION_COMMIT STREQUAL GIT_DESCRIBE_DIRTY) if(VERSION_COMMIT STREQUAL GIT_DESCRIBE_DIRTY)
set(VERSION_COMMIT 0) set(VERSION_COMMIT 0)
endif()
else()
message(WARNING "\"${GIT_DESCRIBE_DIRTY}\" does not match pattern v<major>.<minor>.<patch>-<commit>")
endif() endif()
else() else()
message(WARNING "\"${GIT_DESCRIBE_DIRTY}\" does not match pattern v<major>.<minor>.<patch>-<commit>") message(WARNING "git describe failed with exit code: ${GIT_DESCRIBE_RESULT}")
endif() endif()
else() else()
message(WARNING "git describe failed with exit code: ${GIT_DESCRIBE_RESULT}") message(WARNING "git is not found")
endif() endif()
else()
message(WARNING "git is not found")
endif() endif()
message(STATUS "Proceeding with version: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_COMMIT}") message(STATUS "Proceeding with version: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_COMMIT}")

View File

@@ -71,10 +71,10 @@ option(FLATBUFFERS_ENABLE_PCH
Only work if CMake supports 'target_precompile_headers'. \" Only work if CMake supports 'target_precompile_headers'. \"
This can speed up compilation time." This can speed up compilation time."
OFF) OFF)
option(FLATBUFFERS_SKIP_MONSTER_EXTRA option(FLATBUFFERS_SKIP_MONSTER_EXTRA
"Skip generating monster_extra.fbs that contains non-supported numerical\" "Skip generating monster_extra.fbs that contains non-supported numerical\"
types." OFF) types." OFF)
option(FLATBUFFERS_STRICT_MODE option(FLATBUFFERS_STRICT_MODE
"Build flatbuffers with all warnings as errors (-Werror or /WX)." "Build flatbuffers with all warnings as errors (-Werror or /WX)."
OFF) OFF)
@@ -125,6 +125,13 @@ if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
endif() endif()
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>) add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
if(NOT WIN32)
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
if(NOT HAVE_REALPATH)
add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION)
endif()
endif()
set(FlatBuffers_Library_SRCS set(FlatBuffers_Library_SRCS
include/flatbuffers/allocator.h include/flatbuffers/allocator.h
include/flatbuffers/array.h include/flatbuffers/array.h
@@ -182,6 +189,7 @@ set(FlatBuffers_Compiler_SRCS
src/flatc_main.cpp src/flatc_main.cpp
src/bfbs_gen.h src/bfbs_gen.h
src/bfbs_gen_lua.h src/bfbs_gen_lua.h
src/bfbs_gen_nim.h
src/bfbs_namer.h src/bfbs_namer.h
include/flatbuffers/code_generators.h include/flatbuffers/code_generators.h
src/binary_annotator.h src/binary_annotator.h
@@ -189,6 +197,7 @@ set(FlatBuffers_Compiler_SRCS
src/annotated_binary_text_gen.h src/annotated_binary_text_gen.h
src/annotated_binary_text_gen.cpp src/annotated_binary_text_gen.cpp
src/bfbs_gen_lua.cpp src/bfbs_gen_lua.cpp
src/bfbs_gen_nim.cpp
src/code_generators.cpp src/code_generators.cpp
grpc/src/compiler/schema_interface.h grpc/src/compiler/schema_interface.h
grpc/src/compiler/cpp_generator.h grpc/src/compiler/cpp_generator.h
@@ -217,6 +226,7 @@ set(FlatBuffers_Tests_SRCS
tests/flexbuffers_test.cpp tests/flexbuffers_test.cpp
tests/fuzz_test.cpp tests/fuzz_test.cpp
tests/json_test.cpp tests/json_test.cpp
tests/key_field_test.cpp
tests/monster_test.cpp tests/monster_test.cpp
tests/optional_scalars_test.cpp tests/optional_scalars_test.cpp
tests/parser_test.cpp tests/parser_test.cpp
@@ -255,6 +265,8 @@ set(FlatBuffers_Tests_SRCS
${CMAKE_CURRENT_BINARY_DIR}/tests/native_inline_table_test_generated.h ${CMAKE_CURRENT_BINARY_DIR}/tests/native_inline_table_test_generated.h
# file generate by running compiler on tests/alignment_test.fbs # file generate by running compiler on tests/alignment_test.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/alignment_test_generated.h ${CMAKE_CURRENT_BINARY_DIR}/tests/alignment_test_generated.h
# file generate by running compiler on tests/key_field/key_field_sample.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/key_field/key_field_sample_generated.h
) )
set(FlatBuffers_Tests_CPP17_SRCS set(FlatBuffers_Tests_CPP17_SRCS
@@ -356,8 +368,8 @@ include_directories(grpc)
# Creates an interface library that stores the configuration settings that each # Creates an interface library that stores the configuration settings that each
# target links too. This is a compromise between setting configuration globally # target links too. This is a compromise between setting configuration globally
# with add_compile_options() and the more targetted target_compile_options(). # with add_compile_options() and the more targetted target_compile_options().
# This way each target in this file can share settings and override them if # This way each target in this file can share settings and override them if
# needed. # needed.
add_library(ProjectConfig INTERFACE) add_library(ProjectConfig INTERFACE)
target_compile_features(ProjectConfig target_compile_features(ProjectConfig
@@ -373,7 +385,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
if(MSVC_LIKE) if(MSVC_LIKE)
target_compile_options(ProjectConfig target_compile_options(ProjectConfig
INTERFACE INTERFACE
/W4 /W4
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>: $<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
/WX # Treat all compiler warnings as errors /WX # Treat all compiler warnings as errors
@@ -405,8 +417,8 @@ else()
-Wno-error=stringop-overflow -Wno-error=stringop-overflow
> >
> >
-pedantic -pedantic
-Wextra -Wextra
-Wno-unused-parameter -Wno-unused-parameter
-Wold-style-cast -Wold-style-cast
-fsigned-char -fsigned-char
@@ -414,13 +426,14 @@ else()
# This isn't working for some reason: $<$<CXX_COMPILER_ID:CLANG>: # This isn't working for some reason: $<$<CXX_COMPILER_ID:CLANG>:
$<$<BOOL:${IS_CLANG}>: $<$<BOOL:${IS_CLANG}>:
-Wnewline-eof
-Wno-unknown-warning-option -Wno-unknown-warning-option
-Wmissing-declarations -Wmissing-declarations
-Wzero-as-null-pointer-constant -Wzero-as-null-pointer-constant
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,3.8>: $<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,3.8>:
-Wimplicit-fallthrough -Wimplicit-fallthrough
-Wextra-semi -Wextra-semi
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>: $<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
-Werror=unused-private-field -Werror=unused-private-field
> >
> >
@@ -429,7 +442,7 @@ else()
$<$<CXX_COMPILER_ID:GNU>: $<$<CXX_COMPILER_ID:GNU>:
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,4.4>: $<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,4.4>:
-Wunused-result -Wunused-result
-Wunused-parameter -Wunused-parameter
-Werror=unused-parameter -Werror=unused-parameter
-Wmissing-declarations -Wmissing-declarations
> >
@@ -437,7 +450,7 @@ else()
-Wzero-as-null-pointer-constant -Wzero-as-null-pointer-constant
> >
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,7.0>: $<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,7.0>:
-faligned-new -faligned-new
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>: $<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
-Werror=implicit-fallthrough=2 -Werror=implicit-fallthrough=2
> >
@@ -467,7 +480,7 @@ if(FLATBUFFERS_BUILD_FLATLIB)
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS}) add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
# Attach header directory for when build via add_subdirectory(). # Attach header directory for when build via add_subdirectory().
target_include_directories(flatbuffers target_include_directories(flatbuffers
INTERFACE INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
) )
@@ -485,7 +498,7 @@ if(FLATBUFFERS_BUILD_FLATC)
endif() endif()
target_link_libraries(flatc PRIVATE $<BUILD_INTERFACE:ProjectConfig>) target_link_libraries(flatc PRIVATE $<BUILD_INTERFACE:ProjectConfig>)
target_compile_options(flatc target_compile_options(flatc
PUBLIC PUBLIC
$<$<AND:$<BOOL:${MSVC_LIKE}>,$<CONFIG:Release>>: $<$<AND:$<BOOL:${MSVC_LIKE}>,$<CONFIG:Release>>:
/MT /MT
@@ -576,7 +589,7 @@ function(compile_flatbuffers_schema_to_binary SRC_FBS)
OUTPUT ${GEN_BINARY_SCHEMA} OUTPUT ${GEN_BINARY_SCHEMA}
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
-b --schema --bfbs-comments --bfbs-builtins -b --schema --bfbs-comments --bfbs-builtins
--bfbs-filenames ${SRC_FBS_DIR} --bfbs-filenames "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS_DIR}"
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test" -I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
-o "${SRC_FBS_DIR}" -o "${SRC_FBS_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}" "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
@@ -620,7 +633,7 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs) compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test1.fbs "--no-includes;--gen-compare;--gen-name-strings") compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test1.fbs "--no-includes;--gen-compare;--gen-name-strings")
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test2.fbs "--no-includes;--gen-compare;--gen-name-strings") compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test2.fbs "--no-includes;--gen-compare;--gen-name-strings")
compile_flatbuffers_schema_to_cpp_opt(tests/union_vector/union_vector.fbs "--no-includes;--gen-compare;--gen-name-strings") compile_flatbuffers_schema_to_cpp_opt(tests/union_vector/union_vector.fbs "--no-includes;--gen-compare;")
compile_flatbuffers_schema_to_cpp(tests/optional_scalars.fbs) compile_flatbuffers_schema_to_cpp(tests/optional_scalars.fbs)
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "") compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare") compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
@@ -628,6 +641,7 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare") compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
compile_flatbuffers_schema_to_cpp(tests/native_inline_table_test.fbs "--gen-compare") compile_flatbuffers_schema_to_cpp(tests/native_inline_table_test.fbs "--gen-compare")
compile_flatbuffers_schema_to_cpp(tests/alignment_test.fbs "--gen-compare") compile_flatbuffers_schema_to_cpp(tests/alignment_test.fbs "--gen-compare")
compile_flatbuffers_schema_to_cpp(tests/key_field/key_field_sample.fbs)
if(NOT (MSVC AND (MSVC_VERSION LESS 1900))) if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF. compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
endif() endif()
@@ -687,13 +701,13 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
find_package(gRPC CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED)
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS}) add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
add_dependencies(grpctest generated_code) add_dependencies(grpctest generated_code)
target_link_libraries(grpctext target_link_libraries(grpctext
PRIVATE PRIVATE
$<BUILD_INTERFACE:ProjectConfig> $<BUILD_INTERFACE:ProjectConfig>
gRPC::grpc++_unsecure gRPC::grpc++_unsecure
gRPC::gpr gRPC::gpr
pthread pthread
dl dl
) )
endif() endif()
@@ -706,8 +720,8 @@ if(FLATBUFFERS_INSTALL)
configure_file(CMake/flatbuffers-config-version.cmake.in flatbuffers-config-version.cmake @ONLY) configure_file(CMake/flatbuffers-config-version.cmake.in flatbuffers-config-version.cmake @ONLY)
install( install(
FILES FILES
"CMake/flatbuffers-config.cmake" "CMake/flatbuffers-config.cmake"
"CMake/BuildFlatBuffers.cmake" "CMake/BuildFlatBuffers.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-config-version.cmake" "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-config-version.cmake"
DESTINATION ${FB_CMAKE_DIR} DESTINATION ${FB_CMAKE_DIR}

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'FlatBuffers' s.name = 'FlatBuffers'
s.version = '22.9.24' s.version = '23.1.4'
s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
s.description = "FlatBuffers is a cross platform serialization library architected for s.description = "FlatBuffers is a cross platform serialization library architected for
@@ -11,11 +11,11 @@ Pod::Spec.new do |s|
s.homepage = 'https://github.com/google/flatbuffers' s.homepage = 'https://github.com/google/flatbuffers'
s.license = { :type => 'Apache2.0', :file => 'LICENSE' } s.license = { :type => 'Apache2.0', :file => 'LICENSE' }
s.author = { 'mustii' => 'mustii@mmk.one' } s.author = { 'mustii' => 'mustii@mmk.one' }
s.source = { :git => 'https://github.com/mustiikhalil/flatbuffers.git', :tag => s.version.to_s, :submodules => true } s.source = { :git => 'https://github.com/google/flatbuffers.git', :tag => s.version.to_s, :submodules => true }
s.ios.deployment_target = '11.0' s.ios.deployment_target = '11.0'
s.osx.deployment_target = '10.14' s.osx.deployment_target = '10.14'
s.swift_version = '5.0' s.swift_version = '5.0'
s.source_files = 'Sources/Flatbuffers/*.swift' s.source_files = 'swift/Sources/Flatbuffers/*.swift'
end end

View File

@@ -32,5 +32,6 @@ let package = Package(
.target( .target(
name: "FlatBuffers", name: "FlatBuffers",
dependencies: [], dependencies: [],
path: "swift/Sources",
exclude: ["Documentation.docc/Resources/code/swift"]), exclude: ["Documentation.docc/Resources/code/swift"]),
]) ])

View File

@@ -31,6 +31,7 @@ let package = Package(
targets: [ targets: [
.target( .target(
name: "FlatBuffers", name: "FlatBuffers",
dependencies: []), dependencies: [],
path: "swift/Sources")
]) ])

View File

@@ -33,10 +33,10 @@ swift_rules_extra_dependencies()
http_archive( http_archive(
name = "io_bazel_rules_go", name = "io_bazel_rules_go",
sha256 = "16e9fca53ed6bd4ff4ad76facc9b7b651a89db1689a2877d6fd7b82aa824e366", sha256 = "ae013bf35bd23234d1dea46b079f1e05ba74ac0321423830119d3e787ec73483",
urls = [ urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip", "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.36.0/rules_go-v0.36.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.36.0/rules_go-v0.36.0.zip",
], ],
) )

View File

@@ -3,6 +3,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.FlatBufferTest"> package="com.example.FlatBufferTest">
<uses-sdk android:minSdkVersion="14"/>
<uses-feature android:glEsVersion="0x00020000"></uses-feature> <uses-feature android:glEsVersion="0x00020000"></uses-feature>
<!-- This .apk has no Java code itself, so set hasCode to false. --> <!-- This .apk has no Java code itself, so set hasCode to false. -->

View File

@@ -36,7 +36,7 @@ class Animal : Table() {
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
} }
companion object { companion object {
fun validateVersion() = Constants.FLATBUFFERS_22_9_24() fun validateVersion() = Constants.FLATBUFFERS_23_1_4()
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal()) fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal { fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -9,7 +9,7 @@ class BitWidthUtil {
} }
static BitWidth width(num value) { static BitWidth width(num value) {
if (value.toInt() == value) { if (value is int) {
var v = value.toInt().abs(); var v = value.toInt().abs();
if (v >> 7 == 0) return BitWidth.width8; if (v >> 7 == 0) return BitWidth.width8;
if (v >> 15 == 0) return BitWidth.width16; if (v >> 15 == 0) return BitWidth.width16;

View File

@@ -1,5 +1,5 @@
name: flat_buffers name: flat_buffers
version: 22.9.24 version: 23.1.4
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team. 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 homepage: https://github.com/google/flatbuffers
documentation: https://google.github.io/flatbuffers/index.html documentation: https://google.github.io/flatbuffers/index.html

View File

@@ -0,0 +1,207 @@
// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
class Foo {
Foo._(this._bc, this._bcOffset);
factory Foo(List<int> bytes) {
final rootRef = fb.BufferContext.fromBytes(bytes);
return reader.read(rootRef, 0);
}
static const fb.Reader<Foo> reader = _FooReader();
final fb.BufferContext _bc;
final int _bcOffset;
FooProperties? get myFoo => FooProperties.reader.vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
return 'Foo{myFoo: ${myFoo}}';
}
FooT unpack() => FooT(
myFoo: myFoo?.unpack());
static int pack(fb.Builder fbBuilder, FooT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class FooT implements fb.Packable {
FooPropertiesT? myFoo;
FooT({
this.myFoo});
@override
int pack(fb.Builder fbBuilder) {
fbBuilder.startTable(1);
if (myFoo != null) {
fbBuilder.addStruct(0, myFoo!.pack(fbBuilder));
}
return fbBuilder.endTable();
}
@override
String toString() {
return 'FooT{myFoo: ${myFoo}}';
}
}
class _FooReader extends fb.TableReader<Foo> {
const _FooReader();
@override
Foo createObject(fb.BufferContext bc, int offset) =>
Foo._(bc, offset);
}
class FooBuilder {
FooBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
void begin() {
fbBuilder.startTable(1);
}
int addMyFoo(int offset) {
fbBuilder.addStruct(0, offset);
return fbBuilder.offset;
}
int finish() {
return fbBuilder.endTable();
}
}
class FooObjectBuilder extends fb.ObjectBuilder {
final FooPropertiesObjectBuilder? _myFoo;
FooObjectBuilder({
FooPropertiesObjectBuilder? myFoo,
})
: _myFoo = myFoo;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
fbBuilder.startTable(1);
if (_myFoo != null) {
fbBuilder.addStruct(0, _myFoo!.finish(fbBuilder));
}
return fbBuilder.endTable();
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}
class FooProperties {
FooProperties._(this._bc, this._bcOffset);
static const fb.Reader<FooProperties> reader = _FooPropertiesReader();
final fb.BufferContext _bc;
final int _bcOffset;
bool get a => const fb.BoolReader().read(_bc, _bcOffset + 0);
bool get b => const fb.BoolReader().read(_bc, _bcOffset + 1);
@override
String toString() {
return 'FooProperties{a: ${a}, b: ${b}}';
}
FooPropertiesT unpack() => FooPropertiesT(
a: a,
b: b);
static int pack(fb.Builder fbBuilder, FooPropertiesT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class FooPropertiesT implements fb.Packable {
bool a;
bool b;
FooPropertiesT({
required this.a,
required this.b});
@override
int pack(fb.Builder fbBuilder) {
fbBuilder.putBool(b);
fbBuilder.putBool(a);
return fbBuilder.offset;
}
@override
String toString() {
return 'FooPropertiesT{a: ${a}, b: ${b}}';
}
}
class _FooPropertiesReader extends fb.StructReader<FooProperties> {
const _FooPropertiesReader();
@override
int get size => 2;
@override
FooProperties createObject(fb.BufferContext bc, int offset) =>
FooProperties._(bc, offset);
}
class FooPropertiesBuilder {
FooPropertiesBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
int finish(bool a, bool b) {
fbBuilder.putBool(b);
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;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
fbBuilder.putBool(_b);
fbBuilder.putBool(_a);
return fbBuilder.offset;
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}

View File

@@ -87,7 +87,10 @@ class CheckOtherLangaugesData {
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, ' 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, ' 'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum{value: 0}, ' 'longEnumNonEnumDefault: LongEnum{value: 0}, '
'longEnumNormalDefault: LongEnum{value: 2}}, ' 'longEnumNormalDefault: LongEnum{value: 2}, 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}], ' 'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
'testarrayofstring: [test1, test2], testarrayoftables: null, ' 'testarrayofstring: [test1, test2], testarrayoftables: null, '
'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, ' 'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
@@ -110,7 +113,10 @@ class CheckOtherLangaugesData {
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, ' 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
'nativeInline: null, ' 'nativeInline: null, '
'longEnumNonEnumDefault: LongEnum{value: 0}, ' 'longEnumNonEnumDefault: LongEnum{value: 0}, '
'longEnumNormalDefault: LongEnum{value: 2}}, ' 'longEnumNormalDefault: LongEnum{value: 2}, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
'testnestedflatbuffer: null, testempty: null, testbool: true, ' 'testnestedflatbuffer: null, testempty: null, testbool: true, '
'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, ' 'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, '
'testhashs64Fnv1: 7930699090847568257, ' 'testhashs64Fnv1: 7930699090847568257, '
@@ -137,7 +143,10 @@ class CheckOtherLangaugesData {
'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], ' 'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
'nativeInline: Test{a: 1, b: 2}, ' 'nativeInline: Test{a: 1, b: 2}, '
'longEnumNonEnumDefault: LongEnum{value: 0}, ' 'longEnumNonEnumDefault: LongEnum{value: 0}, '
'longEnumNormalDefault: LongEnum{value: 2}}', 'longEnumNormalDefault: LongEnum{value: 2}, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}'
); );
} }
} }

View File

@@ -40,6 +40,10 @@ void main() {
flx.addInt(-1025); flx.addInt(-1025);
expect(flx.finish(), [255, 251, 5, 2]); expect(flx.finish(), [255, 251, 5, 2]);
} }
{
var builder = Builder()..addDouble(1.0);
expect(builder.finish(), [0, 0, 128, 63, 14, 4]);
}
{ {
var flx = Builder(); var flx = Builder();
flx.addDouble(0.1); flx.addDouble(0.1);

View File

@@ -37,6 +37,7 @@ void main() {
// expect(FlxValue.fromBuffer(b([255, 255, 255, 255, 255, 255, 255, 255, 11, 8])).intValue, 18446744073709551615); // expect(FlxValue.fromBuffer(b([255, 255, 255, 255, 255, 255, 255, 255, 11, 8])).intValue, 18446744073709551615);
}); });
test('double value', () { test('double value', () {
expect(Reference.fromBuffer(b([0, 0, 128, 63, 14, 4])).doubleValue, 1.0);
expect(Reference.fromBuffer(b([0, 0, 144, 64, 14, 4])).doubleValue, 4.5); expect(Reference.fromBuffer(b([0, 0, 144, 64, 14, 4])).doubleValue, 4.5);
expect(Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).doubleValue, expect(Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).doubleValue,
closeTo(.1, .001)); closeTo(.1, .001));

View File

@@ -0,0 +1,109 @@
// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
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;
class TableA {
TableA._(this._bc, this._bcOffset);
factory TableA(List<int> bytes) {
final rootRef = fb.BufferContext.fromBytes(bytes);
return reader.read(rootRef, 0);
}
static const fb.Reader<TableA> reader = _TableAReader();
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);
@override
String toString() {
return 'TableA{b: ${b}}';
}
TableAT unpack() => TableAT(
b: b?.unpack());
static int pack(fb.Builder fbBuilder, TableAT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class TableAT implements fb.Packable {
my_game_other_name_space.TableBT? b;
TableAT({
this.b});
@override
int pack(fb.Builder fbBuilder) {
final int? bOffset = b?.pack(fbBuilder);
fbBuilder.startTable(1);
fbBuilder.addOffset(0, bOffset);
return fbBuilder.endTable();
}
@override
String toString() {
return 'TableAT{b: ${b}}';
}
}
class _TableAReader extends fb.TableReader<TableA> {
const _TableAReader();
@override
TableA createObject(fb.BufferContext bc, int offset) =>
TableA._(bc, offset);
}
class TableABuilder {
TableABuilder(this.fbBuilder);
final fb.Builder fbBuilder;
void begin() {
fbBuilder.startTable(1);
}
int addBOffset(int? offset) {
fbBuilder.addOffset(0, offset);
return fbBuilder.offset;
}
int finish() {
return fbBuilder.endTable();
}
}
class TableAObjectBuilder extends fb.ObjectBuilder {
final my_game_other_name_space.TableBObjectBuilder? _b;
TableAObjectBuilder({
my_game_other_name_space.TableBObjectBuilder? b,
})
: _b = b;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
final int? bOffset = _b?.getOrCreateOffset(fbBuilder);
fbBuilder.startTable(1);
fbBuilder.addOffset(0, bOffset);
return fbBuilder.endTable();
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}

View File

@@ -0,0 +1,241 @@
// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
library my_game.other_name_space;
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './include_test1_generated.dart';
class FromInclude {
final int value;
const FromInclude._(this.value);
factory FromInclude.fromValue(int value) {
final result = values[value];
if (result == null) {
throw StateError('Invalid value $value for bit flag enum FromInclude');
}
return result;
}
static FromInclude? _createOrNull(int? value) =>
value == null ? null : FromInclude.fromValue(value);
static const int minValue = 0;
static const int maxValue = 0;
static bool containsValue(int value) => values.containsKey(value);
static const FromInclude IncludeVal = FromInclude._(0);
static const Map<int, FromInclude> values = {
0: IncludeVal};
static const fb.Reader<FromInclude> reader = _FromIncludeReader();
@override
String toString() {
return 'FromInclude{value: $value}';
}
}
class _FromIncludeReader extends fb.Reader<FromInclude> {
const _FromIncludeReader();
@override
int get size => 8;
@override
FromInclude read(fb.BufferContext bc, int offset) =>
FromInclude.fromValue(const fb.Int64Reader().read(bc, offset));
}
class Unused {
Unused._(this._bc, this._bcOffset);
static const fb.Reader<Unused> reader = _UnusedReader();
final fb.BufferContext _bc;
final int _bcOffset;
int get a => const fb.Int32Reader().read(_bc, _bcOffset + 0);
@override
String toString() {
return 'Unused{a: ${a}}';
}
UnusedT unpack() => UnusedT(
a: a);
static int pack(fb.Builder fbBuilder, UnusedT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class UnusedT implements fb.Packable {
int a;
UnusedT({
required this.a});
@override
int pack(fb.Builder fbBuilder) {
fbBuilder.putInt32(a);
return fbBuilder.offset;
}
@override
String toString() {
return 'UnusedT{a: ${a}}';
}
}
class _UnusedReader extends fb.StructReader<Unused> {
const _UnusedReader();
@override
int get size => 4;
@override
Unused createObject(fb.BufferContext bc, int offset) =>
Unused._(bc, offset);
}
class UnusedBuilder {
UnusedBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
int finish(int a) {
fbBuilder.putInt32(a);
return fbBuilder.offset;
}
}
class UnusedObjectBuilder extends fb.ObjectBuilder {
final int _a;
UnusedObjectBuilder({
required int a,
})
: _a = a;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
fbBuilder.putInt32(_a);
return fbBuilder.offset;
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}
class TableB {
TableB._(this._bc, this._bcOffset);
factory TableB(List<int> bytes) {
final rootRef = fb.BufferContext.fromBytes(bytes);
return reader.read(rootRef, 0);
}
static const fb.Reader<TableB> reader = _TableBReader();
final fb.BufferContext _bc;
final int _bcOffset;
TableA? get a => TableA.reader.vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
return 'TableB{a: ${a}}';
}
TableBT unpack() => TableBT(
a: a?.unpack());
static int pack(fb.Builder fbBuilder, TableBT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class TableBT implements fb.Packable {
TableAT? a;
TableBT({
this.a});
@override
int pack(fb.Builder fbBuilder) {
final int? aOffset = a?.pack(fbBuilder);
fbBuilder.startTable(1);
fbBuilder.addOffset(0, aOffset);
return fbBuilder.endTable();
}
@override
String toString() {
return 'TableBT{a: ${a}}';
}
}
class _TableBReader extends fb.TableReader<TableB> {
const _TableBReader();
@override
TableB createObject(fb.BufferContext bc, int offset) =>
TableB._(bc, offset);
}
class TableBBuilder {
TableBBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
void begin() {
fbBuilder.startTable(1);
}
int addAOffset(int? offset) {
fbBuilder.addOffset(0, offset);
return fbBuilder.offset;
}
int finish() {
return fbBuilder.endTable();
}
}
class TableBObjectBuilder extends fb.ObjectBuilder {
final TableAObjectBuilder? _a;
TableBObjectBuilder({
TableAObjectBuilder? a,
})
: _a = a;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
final int? aOffset = _a?.getOrCreateOffset(fbBuilder);
fbBuilder.startTable(1);
fbBuilder.addOffset(0, aOffset);
return fbBuilder.endTable();
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}

View File

@@ -278,3 +278,122 @@ class KeywordsInTableObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer; return fbBuilder.buffer;
} }
} }
class Table2 {
Table2._(this._bc, this._bcOffset);
factory Table2(List<int> bytes) {
final rootRef = fb.BufferContext.fromBytes(bytes);
return reader.read(rootRef, 0);
}
static const fb.Reader<Table2> reader = _Table2Reader();
final fb.BufferContext _bc;
final int _bcOffset;
KeywordsInUnionTypeId? get typeType => KeywordsInUnionTypeId._createOrNull(const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 4));
dynamic get type {
switch (typeType?.value) {
case 1: return KeywordsInTable.reader.vTableGetNullable(_bc, _bcOffset, 6);
case 2: return KeywordsInTable.reader.vTableGetNullable(_bc, _bcOffset, 6);
default: return null;
}
}
@override
String toString() {
return 'Table2{typeType: ${typeType}, type: ${type}}';
}
Table2T unpack() => Table2T(
typeType: typeType,
type: type);
static int pack(fb.Builder fbBuilder, Table2T? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class Table2T implements fb.Packable {
KeywordsInUnionTypeId? typeType;
dynamic type;
Table2T({
this.typeType,
this.type});
@override
int pack(fb.Builder fbBuilder) {
final int? typeOffset = type?.pack(fbBuilder);
fbBuilder.startTable(2);
fbBuilder.addUint8(0, typeType?.value);
fbBuilder.addOffset(1, typeOffset);
return fbBuilder.endTable();
}
@override
String toString() {
return 'Table2T{typeType: ${typeType}, type: ${type}}';
}
}
class _Table2Reader extends fb.TableReader<Table2> {
const _Table2Reader();
@override
Table2 createObject(fb.BufferContext bc, int offset) =>
Table2._(bc, offset);
}
class Table2Builder {
Table2Builder(this.fbBuilder);
final fb.Builder fbBuilder;
void begin() {
fbBuilder.startTable(2);
}
int addTypeType(KeywordsInUnionTypeId? typeType) {
fbBuilder.addUint8(0, typeType?.value);
return fbBuilder.offset;
}
int addTypeOffset(int? offset) {
fbBuilder.addOffset(1, offset);
return fbBuilder.offset;
}
int finish() {
return fbBuilder.endTable();
}
}
class Table2ObjectBuilder extends fb.ObjectBuilder {
final KeywordsInUnionTypeId? _typeType;
final dynamic _type;
Table2ObjectBuilder({
KeywordsInUnionTypeId? typeType,
dynamic type,
})
: _typeType = typeType,
_type = type;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
final int? typeOffset = _type?.getOrCreateOffset(fbBuilder);
fbBuilder.startTable(2);
fbBuilder.addUint8(0, _typeType?.value);
fbBuilder.addOffset(1, typeOffset);
return fbBuilder.endTable();
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}

View File

@@ -0,0 +1,155 @@
// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
class OptionsEnum {
final int value;
const OptionsEnum._(this.value);
factory OptionsEnum.fromValue(int value) {
final result = values[value];
if (result == null) {
throw StateError('Invalid value $value for bit flag enum OptionsEnum');
}
return result;
}
static OptionsEnum? _createOrNull(int? value) =>
value == null ? null : OptionsEnum.fromValue(value);
static const int minValue = 1;
static const int maxValue = 3;
static bool containsValue(int value) => values.containsKey(value);
static const OptionsEnum A = OptionsEnum._(1);
static const OptionsEnum B = OptionsEnum._(2);
static const OptionsEnum C = OptionsEnum._(3);
static const Map<int, OptionsEnum> values = {
1: A,
2: B,
3: C};
static const fb.Reader<OptionsEnum> reader = _OptionsEnumReader();
@override
String toString() {
return 'OptionsEnum{value: $value}';
}
}
class _OptionsEnumReader extends fb.Reader<OptionsEnum> {
const _OptionsEnumReader();
@override
int get size => 4;
@override
OptionsEnum read(fb.BufferContext bc, int offset) =>
OptionsEnum.fromValue(const fb.Uint32Reader().read(bc, offset));
}
class MyTable {
MyTable._(this._bc, this._bcOffset);
factory MyTable(List<int> bytes) {
final rootRef = fb.BufferContext.fromBytes(bytes);
return reader.read(rootRef, 0);
}
static const fb.Reader<MyTable> reader = _MyTableReader();
final fb.BufferContext _bc;
final int _bcOffset;
List<OptionsEnum>? get options => const fb.ListReader<OptionsEnum>(OptionsEnum.reader).vTableGetNullable(_bc, _bcOffset, 4);
@override
String toString() {
return 'MyTable{options: ${options}}';
}
MyTableT unpack() => MyTableT(
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;
return object.pack(fbBuilder);
}
}
class MyTableT implements fb.Packable {
List<OptionsEnum>? options;
MyTableT({
this.options});
@override
int pack(fb.Builder fbBuilder) {
final int? optionsOffset = options == null ? null
: fbBuilder.writeListUint32(options!.map((f) => f.value).toList());
fbBuilder.startTable(1);
fbBuilder.addOffset(0, optionsOffset);
return fbBuilder.endTable();
}
@override
String toString() {
return 'MyTableT{options: ${options}}';
}
}
class _MyTableReader extends fb.TableReader<MyTable> {
const _MyTableReader();
@override
MyTable createObject(fb.BufferContext bc, int offset) =>
MyTable._(bc, offset);
}
class MyTableBuilder {
MyTableBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
void begin() {
fbBuilder.startTable(1);
}
int addOptionsOffset(int? offset) {
fbBuilder.addOffset(0, offset);
return fbBuilder.offset;
}
int finish() {
return fbBuilder.endTable();
}
}
class MyTableObjectBuilder extends fb.ObjectBuilder {
final List<OptionsEnum>? _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
: fbBuilder.writeListUint32(_options!.map((f) => f.value).toList());
fbBuilder.startTable(1);
fbBuilder.addOffset(0, optionsOffset);
return fbBuilder.endTable();
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}

View File

@@ -31,6 +31,14 @@ enum Race:byte {
Elf, Elf,
} }
enum LongEnum:ulong (bit_flags) {
LongOne = 1,
LongTwo = 2,
// Because this is a bitflag, 40 will be out of range of a 32-bit integer,
// allowing us to exercise any logic special to big numbers.
LongBig = 40,
}
union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster } union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster }
union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster } union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster }
@@ -62,6 +70,10 @@ struct StructOfStructs {
c: Ability; c: Ability;
} }
struct StructOfStructsOfStructs {
a: StructOfStructs;
}
table Stat { table Stat {
id:string; id:string;
val:long; val:long;
@@ -124,6 +136,20 @@ table Monster {
signed_enum:Race = None (id:48); signed_enum:Race = None (id:48);
testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster"); testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster");
scalar_key_sorted_tables:[Stat] (id: 50); scalar_key_sorted_tables:[Stat] (id: 50);
native_inline:Test (id: 51, native_inline);
// The default value of this enum will be a numeric zero, which isn't a valid
// enum value.
long_enum_non_enum_default:LongEnum (id: 52);
long_enum_normal_default:LongEnum = LongOne (id: 53);
// Test that default values nan and +/-inf work.
nan_default:float = nan (id: 54);
inf_default:float = inf (id: 55);
positive_inf_default:float = +inf (id: 56);
infinity_default:float = infinity (id: 57);
positive_infinity_default:float = +infinity (id: 58);
negative_inf_default:float = -inf (id: 59);
negative_infinity_default:float = -infinity (id: 60);
double_inf_default:double = inf (id: 61);
} }
table TypeAliases { table TypeAliases {

View File

@@ -9,6 +9,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_test_my_game_generated.dart' as my_game; import './monster_test_my_game_generated.dart' as my_game;
import './monster_test_my_game.example_generated.dart' as my_game_example; import './monster_test_my_game.example_generated.dart' as my_game_example;
import './include_test1_generated.dart';
class Monster { class Monster {
Monster._(this._bc, this._bcOffset); Monster._(this._bc, this._bcOffset);
factory Monster(List<int> bytes) { factory Monster(List<int> bytes) {

View File

@@ -9,6 +9,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_test_my_game_generated.dart' as my_game; import './monster_test_my_game_generated.dart' as my_game;
import './monster_test_my_game.example2_generated.dart' as my_game_example2; import './monster_test_my_game.example2_generated.dart' as my_game_example2;
import './include_test1_generated.dart';
/// Composite components of Monster color. /// Composite components of Monster color.
class Color { class Color {
final int value; final int value;
@@ -17,7 +19,11 @@ class Color {
factory Color.fromValue(int value) { factory Color.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum Color'); if (value == 0) {
return Color._(0);
} else {
throw StateError('Invalid value $value for bit flag enum Color');
}
} }
return result; return result;
} }
@@ -66,7 +72,7 @@ class Race {
factory Race.fromValue(int value) { factory Race.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum Race'); throw StateError('Invalid value $value for bit flag enum Race');
} }
return result; return result;
} }
@@ -107,6 +113,54 @@ class _RaceReader extends fb.Reader<Race> {
Race.fromValue(const fb.Int8Reader().read(bc, offset)); Race.fromValue(const fb.Int8Reader().read(bc, offset));
} }
class LongEnum {
final int value;
const LongEnum._(this.value);
factory LongEnum.fromValue(int value) {
final result = values[value];
if (result == null) {
if (value == 0) {
return LongEnum._(0);
} else {
throw StateError('Invalid value $value for bit flag enum LongEnum');
}
}
return result;
}
static LongEnum? _createOrNull(int? value) =>
value == null ? null : LongEnum.fromValue(value);
static bool containsValue(int value) => values.containsKey(value);
static const LongEnum LongOne = LongEnum._(2);
static const LongEnum LongTwo = LongEnum._(4);
static const LongEnum LongBig = LongEnum._(1099511627776);
static const Map<int, LongEnum> values = {
2: LongOne,
4: LongTwo,
1099511627776: LongBig};
static const fb.Reader<LongEnum> reader = _LongEnumReader();
@override
String toString() {
return 'LongEnum{value: $value}';
}
}
class _LongEnumReader extends fb.Reader<LongEnum> {
const _LongEnumReader();
@override
int get size => 8;
@override
LongEnum read(fb.BufferContext bc, int offset) =>
LongEnum.fromValue(const fb.Uint64Reader().read(bc, offset));
}
class AnyTypeId { class AnyTypeId {
final int value; final int value;
const AnyTypeId._(this.value); const AnyTypeId._(this.value);
@@ -114,7 +168,7 @@ class AnyTypeId {
factory AnyTypeId.fromValue(int value) { factory AnyTypeId.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum AnyTypeId'); throw StateError('Invalid value $value for bit flag enum AnyTypeId');
} }
return result; return result;
} }
@@ -162,7 +216,7 @@ class AnyUniqueAliasesTypeId {
factory AnyUniqueAliasesTypeId.fromValue(int value) { factory AnyUniqueAliasesTypeId.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum AnyUniqueAliasesTypeId'); throw StateError('Invalid value $value for bit flag enum AnyUniqueAliasesTypeId');
} }
return result; return result;
} }
@@ -210,7 +264,7 @@ class AnyAmbiguousAliasesTypeId {
factory AnyAmbiguousAliasesTypeId.fromValue(int value) { factory AnyAmbiguousAliasesTypeId.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum AnyAmbiguousAliasesTypeId'); throw StateError('Invalid value $value for bit flag enum AnyAmbiguousAliasesTypeId');
} }
return result; return result;
} }
@@ -264,7 +318,7 @@ class Test {
@override @override
String toString() { String toString() {
return 'Test{a: $a, b: $b}'; return 'Test{a: ${a}, b: ${b}}';
} }
TestT unpack() => TestT( TestT unpack() => TestT(
@@ -295,7 +349,7 @@ class TestT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'TestT{a: $a, b: $b}'; return 'TestT{a: ${a}, b: ${b}}';
} }
} }
@@ -368,7 +422,7 @@ class TestSimpleTableWithEnum {
@override @override
String toString() { String toString() {
return 'TestSimpleTableWithEnum{color: $color}'; return 'TestSimpleTableWithEnum{color: ${color}}';
} }
TestSimpleTableWithEnumT unpack() => TestSimpleTableWithEnumT( TestSimpleTableWithEnumT unpack() => TestSimpleTableWithEnumT(
@@ -395,7 +449,7 @@ class TestSimpleTableWithEnumT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'TestSimpleTableWithEnumT{color: $color}'; return 'TestSimpleTableWithEnumT{color: ${color}}';
} }
} }
@@ -467,7 +521,7 @@ class Vec3 {
@override @override
String toString() { String toString() {
return 'Vec3{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}'; return 'Vec3{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}';
} }
Vec3T unpack() => Vec3T( Vec3T unpack() => Vec3T(
@@ -516,7 +570,7 @@ class Vec3T implements fb.Packable {
@override @override
String toString() { String toString() {
return 'Vec3T{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}'; return 'Vec3T{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}';
} }
} }
@@ -610,7 +664,7 @@ class Ability {
@override @override
String toString() { String toString() {
return 'Ability{id: $id, distance: $distance}'; return 'Ability{id: ${id}, distance: ${distance}}';
} }
AbilityT unpack() => AbilityT( AbilityT unpack() => AbilityT(
@@ -640,7 +694,7 @@ class AbilityT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'AbilityT{id: $id, distance: $distance}'; return 'AbilityT{id: ${id}, distance: ${distance}}';
} }
} }
@@ -709,7 +763,7 @@ class StructOfStructs {
@override @override
String toString() { String toString() {
return 'StructOfStructs{a: $a, b: $b, c: $c}'; return 'StructOfStructs{a: ${a}, b: ${b}, c: ${c}}';
} }
StructOfStructsT unpack() => StructOfStructsT( StructOfStructsT unpack() => StructOfStructsT(
@@ -743,7 +797,7 @@ class StructOfStructsT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'StructOfStructsT{a: $a, b: $b, c: $c}'; return 'StructOfStructsT{a: ${a}, b: ${b}, c: ${c}}';
} }
} }
@@ -803,6 +857,94 @@ class StructOfStructsObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer; return fbBuilder.buffer;
} }
} }
class StructOfStructsOfStructs {
StructOfStructsOfStructs._(this._bc, this._bcOffset);
static const fb.Reader<StructOfStructsOfStructs> reader = _StructOfStructsOfStructsReader();
final fb.BufferContext _bc;
final int _bcOffset;
StructOfStructs get a => StructOfStructs.reader.read(_bc, _bcOffset + 0);
@override
String toString() {
return 'StructOfStructsOfStructs{a: ${a}}';
}
StructOfStructsOfStructsT unpack() => StructOfStructsOfStructsT(
a: a.unpack());
static int pack(fb.Builder fbBuilder, StructOfStructsOfStructsT? object) {
if (object == null) return 0;
return object.pack(fbBuilder);
}
}
class StructOfStructsOfStructsT implements fb.Packable {
StructOfStructsT a;
StructOfStructsOfStructsT({
required this.a});
@override
int pack(fb.Builder fbBuilder) {
a.pack(fbBuilder);
return fbBuilder.offset;
}
@override
String toString() {
return 'StructOfStructsOfStructsT{a: ${a}}';
}
}
class _StructOfStructsOfStructsReader extends fb.StructReader<StructOfStructsOfStructs> {
const _StructOfStructsOfStructsReader();
@override
int get size => 20;
@override
StructOfStructsOfStructs createObject(fb.BufferContext bc, int offset) =>
StructOfStructsOfStructs._(bc, offset);
}
class StructOfStructsOfStructsBuilder {
StructOfStructsOfStructsBuilder(this.fbBuilder);
final fb.Builder fbBuilder;
int finish(fb.StructBuilder a) {
a();
return fbBuilder.offset;
}
}
class StructOfStructsOfStructsObjectBuilder extends fb.ObjectBuilder {
final StructOfStructsObjectBuilder _a;
StructOfStructsOfStructsObjectBuilder({
required StructOfStructsObjectBuilder a,
})
: _a = a;
/// Finish building, and store into the [fbBuilder].
@override
int finish(fb.Builder fbBuilder) {
_a.finish(fbBuilder);
return fbBuilder.offset;
}
/// Convenience method to serialize to byte list.
@override
Uint8List toBytes([String? fileIdentifier]) {
final fbBuilder = fb.Builder(deduplicateTables: false);
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
return fbBuilder.buffer;
}
}
class Stat { class Stat {
Stat._(this._bc, this._bcOffset); Stat._(this._bc, this._bcOffset);
factory Stat(List<int> bytes) { factory Stat(List<int> bytes) {
@@ -821,7 +963,7 @@ class Stat {
@override @override
String toString() { String toString() {
return 'Stat{id: $id, val: $val, count: $count}'; return 'Stat{id: ${id}, val: ${val}, count: ${count}}';
} }
StatT unpack() => StatT( StatT unpack() => StatT(
@@ -858,7 +1000,7 @@ class StatT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'StatT{id: $id, val: $val, count: $count}'; return 'StatT{id: ${id}, val: ${val}, count: ${count}}';
} }
} }
@@ -947,7 +1089,7 @@ class Referrable {
@override @override
String toString() { String toString() {
return 'Referrable{id: $id}'; return 'Referrable{id: ${id}}';
} }
ReferrableT unpack() => ReferrableT( ReferrableT unpack() => ReferrableT(
@@ -974,7 +1116,7 @@ class ReferrableT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'ReferrableT{id: $id}'; return 'ReferrableT{id: ${id}}';
} }
} }
@@ -1115,10 +1257,21 @@ class Monster {
Race get signedEnum => Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1)); Race get signedEnum => Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1));
List<int>? get testrequirednestedflatbuffer => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 102); List<int>? get testrequirednestedflatbuffer => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 102);
List<Stat>? get scalarKeySortedTables => const fb.ListReader<Stat>(Stat.reader).vTableGetNullable(_bc, _bcOffset, 104); List<Stat>? get scalarKeySortedTables => const fb.ListReader<Stat>(Stat.reader).vTableGetNullable(_bc, _bcOffset, 104);
Test? get nativeInline => Test.reader.vTableGetNullable(_bc, _bcOffset, 106);
LongEnum get longEnumNonEnumDefault => LongEnum.fromValue(const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 108, 0));
LongEnum get longEnumNormalDefault => LongEnum.fromValue(const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 110, 2));
double get nanDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 112, double.nan);
double get infDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 114, double.infinity);
double get positiveInfDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 116, double.infinity);
double get infinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 118, double.infinity);
double get positiveInfinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 120, double.infinity);
double get negativeInfDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 122, double.negativeInfinity);
double get negativeInfinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 124, double.negativeInfinity);
double get doubleInfDefault => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 126, double.infinity);
@override @override
String toString() { String toString() {
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables}'; return 'Monster{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}';
} }
MonsterT unpack() => MonsterT( MonsterT unpack() => MonsterT(
@@ -1171,7 +1324,18 @@ class Monster {
vectorOfEnums: const fb.ListReader<Color>(Color.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 98), vectorOfEnums: const fb.ListReader<Color>(Color.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 98),
signedEnum: signedEnum, signedEnum: signedEnum,
testrequirednestedflatbuffer: const fb.Uint8ListReader(lazy: false).vTableGetNullable(_bc, _bcOffset, 102), testrequirednestedflatbuffer: const fb.Uint8ListReader(lazy: false).vTableGetNullable(_bc, _bcOffset, 102),
scalarKeySortedTables: scalarKeySortedTables?.map((e) => e.unpack()).toList()); scalarKeySortedTables: scalarKeySortedTables?.map((e) => e.unpack()).toList(),
nativeInline: nativeInline?.unpack(),
longEnumNonEnumDefault: longEnumNonEnumDefault,
longEnumNormalDefault: longEnumNormalDefault,
nanDefault: nanDefault,
infDefault: infDefault,
positiveInfDefault: positiveInfDefault,
infinityDefault: infinityDefault,
positiveInfinityDefault: positiveInfinityDefault,
negativeInfDefault: negativeInfDefault,
negativeInfinityDefault: negativeInfinityDefault,
doubleInfDefault: doubleInfDefault);
static int pack(fb.Builder fbBuilder, MonsterT? object) { static int pack(fb.Builder fbBuilder, MonsterT? object) {
if (object == null) return 0; if (object == null) return 0;
@@ -1233,6 +1397,17 @@ class MonsterT implements fb.Packable {
Race signedEnum; Race signedEnum;
List<int>? testrequirednestedflatbuffer; List<int>? testrequirednestedflatbuffer;
List<StatT>? scalarKeySortedTables; List<StatT>? scalarKeySortedTables;
TestT? nativeInline;
LongEnum longEnumNonEnumDefault;
LongEnum longEnumNormalDefault;
double nanDefault;
double infDefault;
double positiveInfDefault;
double infinityDefault;
double positiveInfinityDefault;
double negativeInfDefault;
double negativeInfinityDefault;
double doubleInfDefault;
MonsterT({ MonsterT({
this.pos, this.pos,
@@ -1284,7 +1459,18 @@ class MonsterT implements fb.Packable {
this.vectorOfEnums, this.vectorOfEnums,
this.signedEnum = Race.None, this.signedEnum = Race.None,
this.testrequirednestedflatbuffer, this.testrequirednestedflatbuffer,
this.scalarKeySortedTables}); this.scalarKeySortedTables,
this.nativeInline,
this.longEnumNonEnumDefault = const LongEnum._(0),
this.longEnumNormalDefault = LongEnum.LongOne,
this.nanDefault = double.nan,
this.infDefault = double.infinity,
this.positiveInfDefault = double.infinity,
this.infinityDefault = double.infinity,
this.positiveInfinityDefault = double.infinity,
this.negativeInfDefault = double.negativeInfinity,
this.negativeInfinityDefault = double.negativeInfinity,
this.doubleInfDefault = double.infinity});
@override @override
int pack(fb.Builder fbBuilder) { int pack(fb.Builder fbBuilder) {
@@ -1345,7 +1531,7 @@ class MonsterT implements fb.Packable {
: fbBuilder.writeListUint8(testrequirednestedflatbuffer!); : fbBuilder.writeListUint8(testrequirednestedflatbuffer!);
final int? scalarKeySortedTablesOffset = scalarKeySortedTables == null ? null final int? scalarKeySortedTablesOffset = scalarKeySortedTables == null ? null
: fbBuilder.writeList(scalarKeySortedTables!.map((b) => b.pack(fbBuilder)).toList()); : fbBuilder.writeList(scalarKeySortedTables!.map((b) => b.pack(fbBuilder)).toList());
fbBuilder.startTable(50); fbBuilder.startTable(62);
if (pos != null) { if (pos != null) {
fbBuilder.addStruct(0, pos!.pack(fbBuilder)); fbBuilder.addStruct(0, pos!.pack(fbBuilder));
} }
@@ -1398,12 +1584,25 @@ class MonsterT implements fb.Packable {
fbBuilder.addInt8(48, signedEnum.value); fbBuilder.addInt8(48, signedEnum.value);
fbBuilder.addOffset(49, testrequirednestedflatbufferOffset); fbBuilder.addOffset(49, testrequirednestedflatbufferOffset);
fbBuilder.addOffset(50, scalarKeySortedTablesOffset); fbBuilder.addOffset(50, scalarKeySortedTablesOffset);
if (nativeInline != null) {
fbBuilder.addStruct(51, nativeInline!.pack(fbBuilder));
}
fbBuilder.addUint64(52, longEnumNonEnumDefault.value);
fbBuilder.addUint64(53, longEnumNormalDefault.value);
fbBuilder.addFloat32(54, nanDefault);
fbBuilder.addFloat32(55, infDefault);
fbBuilder.addFloat32(56, positiveInfDefault);
fbBuilder.addFloat32(57, infinityDefault);
fbBuilder.addFloat32(58, positiveInfinityDefault);
fbBuilder.addFloat32(59, negativeInfDefault);
fbBuilder.addFloat32(60, negativeInfinityDefault);
fbBuilder.addFloat64(61, doubleInfDefault);
return fbBuilder.endTable(); return fbBuilder.endTable();
} }
@override @override
String toString() { String toString() {
return 'MonsterT{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables}'; return 'MonsterT{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}';
} }
} }
@@ -1421,7 +1620,7 @@ class MonsterBuilder {
final fb.Builder fbBuilder; final fb.Builder fbBuilder;
void begin() { void begin() {
fbBuilder.startTable(50); fbBuilder.startTable(62);
} }
int addPos(int offset) { int addPos(int offset) {
@@ -1624,6 +1823,50 @@ class MonsterBuilder {
fbBuilder.addOffset(50, offset); fbBuilder.addOffset(50, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addNativeInline(int offset) {
fbBuilder.addStruct(51, offset);
return fbBuilder.offset;
}
int addLongEnumNonEnumDefault(LongEnum? longEnumNonEnumDefault) {
fbBuilder.addUint64(52, longEnumNonEnumDefault?.value);
return fbBuilder.offset;
}
int addLongEnumNormalDefault(LongEnum? longEnumNormalDefault) {
fbBuilder.addUint64(53, longEnumNormalDefault?.value);
return fbBuilder.offset;
}
int addNanDefault(double? nanDefault) {
fbBuilder.addFloat32(54, nanDefault);
return fbBuilder.offset;
}
int addInfDefault(double? infDefault) {
fbBuilder.addFloat32(55, infDefault);
return fbBuilder.offset;
}
int addPositiveInfDefault(double? positiveInfDefault) {
fbBuilder.addFloat32(56, positiveInfDefault);
return fbBuilder.offset;
}
int addInfinityDefault(double? infinityDefault) {
fbBuilder.addFloat32(57, infinityDefault);
return fbBuilder.offset;
}
int addPositiveInfinityDefault(double? positiveInfinityDefault) {
fbBuilder.addFloat32(58, positiveInfinityDefault);
return fbBuilder.offset;
}
int addNegativeInfDefault(double? negativeInfDefault) {
fbBuilder.addFloat32(59, negativeInfDefault);
return fbBuilder.offset;
}
int addNegativeInfinityDefault(double? negativeInfinityDefault) {
fbBuilder.addFloat32(60, negativeInfinityDefault);
return fbBuilder.offset;
}
int addDoubleInfDefault(double? doubleInfDefault) {
fbBuilder.addFloat64(61, doubleInfDefault);
return fbBuilder.offset;
}
int finish() { int finish() {
return fbBuilder.endTable(); return fbBuilder.endTable();
@@ -1681,6 +1924,17 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
final Race? _signedEnum; final Race? _signedEnum;
final List<int>? _testrequirednestedflatbuffer; final List<int>? _testrequirednestedflatbuffer;
final List<StatObjectBuilder>? _scalarKeySortedTables; final List<StatObjectBuilder>? _scalarKeySortedTables;
final TestObjectBuilder? _nativeInline;
final LongEnum? _longEnumNonEnumDefault;
final LongEnum? _longEnumNormalDefault;
final double? _nanDefault;
final double? _infDefault;
final double? _positiveInfDefault;
final double? _infinityDefault;
final double? _positiveInfinityDefault;
final double? _negativeInfDefault;
final double? _negativeInfinityDefault;
final double? _doubleInfDefault;
MonsterObjectBuilder({ MonsterObjectBuilder({
Vec3ObjectBuilder? pos, Vec3ObjectBuilder? pos,
@@ -1733,6 +1987,17 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
Race? signedEnum, Race? signedEnum,
List<int>? testrequirednestedflatbuffer, List<int>? testrequirednestedflatbuffer,
List<StatObjectBuilder>? scalarKeySortedTables, List<StatObjectBuilder>? scalarKeySortedTables,
TestObjectBuilder? nativeInline,
LongEnum? longEnumNonEnumDefault,
LongEnum? longEnumNormalDefault,
double? nanDefault,
double? infDefault,
double? positiveInfDefault,
double? infinityDefault,
double? positiveInfinityDefault,
double? negativeInfDefault,
double? negativeInfinityDefault,
double? doubleInfDefault,
}) })
: _pos = pos, : _pos = pos,
_mana = mana, _mana = mana,
@@ -1783,7 +2048,18 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
_vectorOfEnums = vectorOfEnums, _vectorOfEnums = vectorOfEnums,
_signedEnum = signedEnum, _signedEnum = signedEnum,
_testrequirednestedflatbuffer = testrequirednestedflatbuffer, _testrequirednestedflatbuffer = testrequirednestedflatbuffer,
_scalarKeySortedTables = scalarKeySortedTables; _scalarKeySortedTables = scalarKeySortedTables,
_nativeInline = nativeInline,
_longEnumNonEnumDefault = longEnumNonEnumDefault,
_longEnumNormalDefault = longEnumNormalDefault,
_nanDefault = nanDefault,
_infDefault = infDefault,
_positiveInfDefault = positiveInfDefault,
_infinityDefault = infinityDefault,
_positiveInfinityDefault = positiveInfinityDefault,
_negativeInfDefault = negativeInfDefault,
_negativeInfinityDefault = negativeInfinityDefault,
_doubleInfDefault = doubleInfDefault;
/// Finish building, and store into the [fbBuilder]. /// Finish building, and store into the [fbBuilder].
@override @override
@@ -1836,7 +2112,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
: fbBuilder.writeListUint8(_testrequirednestedflatbuffer!); : fbBuilder.writeListUint8(_testrequirednestedflatbuffer!);
final int? scalarKeySortedTablesOffset = _scalarKeySortedTables == null ? null final int? scalarKeySortedTablesOffset = _scalarKeySortedTables == null ? null
: fbBuilder.writeList(_scalarKeySortedTables!.map((b) => b.getOrCreateOffset(fbBuilder)).toList()); : fbBuilder.writeList(_scalarKeySortedTables!.map((b) => b.getOrCreateOffset(fbBuilder)).toList());
fbBuilder.startTable(50); fbBuilder.startTable(62);
if (_pos != null) { if (_pos != null) {
fbBuilder.addStruct(0, _pos!.finish(fbBuilder)); fbBuilder.addStruct(0, _pos!.finish(fbBuilder));
} }
@@ -1889,6 +2165,19 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
fbBuilder.addInt8(48, _signedEnum?.value); fbBuilder.addInt8(48, _signedEnum?.value);
fbBuilder.addOffset(49, testrequirednestedflatbufferOffset); fbBuilder.addOffset(49, testrequirednestedflatbufferOffset);
fbBuilder.addOffset(50, scalarKeySortedTablesOffset); fbBuilder.addOffset(50, scalarKeySortedTablesOffset);
if (_nativeInline != null) {
fbBuilder.addStruct(51, _nativeInline!.finish(fbBuilder));
}
fbBuilder.addUint64(52, _longEnumNonEnumDefault?.value);
fbBuilder.addUint64(53, _longEnumNormalDefault?.value);
fbBuilder.addFloat32(54, _nanDefault);
fbBuilder.addFloat32(55, _infDefault);
fbBuilder.addFloat32(56, _positiveInfDefault);
fbBuilder.addFloat32(57, _infinityDefault);
fbBuilder.addFloat32(58, _positiveInfinityDefault);
fbBuilder.addFloat32(59, _negativeInfDefault);
fbBuilder.addFloat32(60, _negativeInfinityDefault);
fbBuilder.addFloat64(61, _doubleInfDefault);
return fbBuilder.endTable(); return fbBuilder.endTable();
} }
@@ -1927,7 +2216,7 @@ class TypeAliases {
@override @override
String toString() { String toString() {
return 'TypeAliases{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}'; return 'TypeAliases{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}';
} }
TypeAliasesT unpack() => TypeAliasesT( TypeAliasesT unpack() => TypeAliasesT(
@@ -2002,7 +2291,7 @@ class TypeAliasesT implements fb.Packable {
@override @override
String toString() { String toString() {
return 'TypeAliasesT{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}'; return 'TypeAliasesT{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}';
} }
} }

View File

@@ -9,6 +9,8 @@ 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.example_generated.dart' as my_game_example;
import './monster_test_my_game.example2_generated.dart' as my_game_example2; import './monster_test_my_game.example2_generated.dart' as my_game_example2;
import './include_test1_generated.dart';
class InParentNamespace { class InParentNamespace {
InParentNamespace._(this._bc, this._bcOffset); InParentNamespace._(this._bc, this._bcOffset);
factory InParentNamespace(List<int> bytes) { factory InParentNamespace(List<int> bytes) {

Binary file not shown.

View File

@@ -82,7 +82,7 @@ pass to the `GetRootAsMyRootType` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
using MyGame.Example; using MyGame.Example;
using FlatBuffers; using Google.FlatBuffers;
// This snippet ignores exceptions for brevity. // This snippet ignores exceptions for brevity.
byte[] data = File.ReadAllBytes("monsterdata_test.mon"); byte[] data = File.ReadAllBytes("monsterdata_test.mon");

View File

@@ -10,7 +10,7 @@ include = `include` string\_constant `;`
namespace\_decl = `namespace` ident ( `.` ident )* `;` namespace\_decl = `namespace` ident ( `.` ident )* `;`
attribute\_decl = `attribute` ident | `"`ident`"` `;` attribute\_decl = `attribute` ident | `"` ident `"` `;`
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}` type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
@@ -31,7 +31,7 @@ type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
`float32` | `float64` | `float32` | `float64` |
`string` | `[` type `]` | ident `string` | `[` type `]` | ident
enumval\_decl = ident [ `=` integer\_constant ] enumval\_decl = ident [ `=` integer\_constant ] metadata
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ] metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]

View File

@@ -4,7 +4,7 @@ To generate the docs for FlatBuffers from the source files, you
will first need to install two programs. will first need to install two programs.
1. You will need to install `doxygen`. See 1. You will need to install `doxygen`. See
[Download Doxygen](http://www.stack.nl/~dimitri/doxygen/download.html). [Download Doxygen](https://doxygen.nl/download.html).
2. You will need to install `doxypypy` to format python comments appropriately. 2. You will need to install `doxypypy` to format python comments appropriately.
Install it from [here](https://github.com/Feneric/doxypypy). Install it from [here](https://github.com/Feneric/doxypypy).

View File

@@ -309,11 +309,11 @@ in the corresponding C++ code. Multiple such lines per item are allowed.
### Attributes ### Attributes
Attributes may be attached to a declaration, behind a field, or after Attributes may be attached to a declaration, behind a field/enum value,
the name of a table/struct/enum/union. These may either have a value or or after the name of a table/struct/enum/union. These may either have
not. Some attributes like `deprecated` are understood by the compiler; a value or not. Some attributes like `deprecated` are understood by
user defined ones need to be declared with the attribute declaration the compiler; user defined ones need to be declared with the attribute
(like `priority` in the example above), and are declaration (like `priority` in the example above), and are
available to query if you parse the schema at runtime. available to query if you parse the schema at runtime.
This is useful if you write your own code generators/editors etc., and 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 you wish to add additional information specific to your tool (such as a
@@ -552,7 +552,7 @@ 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 should always generate a merge conflict if two people try to allocate the same
id. id.
### Schema evolution examples ### Schema evolution examples (tables)
Some examples to clarify what happens as you change a schema: Some examples to clarify what happens as you change a schema:
@@ -614,6 +614,41 @@ 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 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 incompatible with the actual binary buffers, since those only ever address
fields by id/offset. 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> <br>
### Testing whether a field is present in a table ### Testing whether a field is present in a table

View File

@@ -415,7 +415,7 @@ The first step is to import/include the library, generated files, etc.
</div> </div>
<div class="language-csharp"> <div class="language-csharp">
~~~{.cs} ~~~{.cs}
using FlatBuffers; using Google.FlatBuffers;
using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.) using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.)
~~~ ~~~
</div> </div>
@@ -2200,7 +2200,7 @@ before:
</div> </div>
<div class="language-csharp"> <div class="language-csharp">
~~~{.cs} ~~~{.cs}
using FlatBuffers; using Google.FlatBuffers;
using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.) using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.)
~~~ ~~~
</div> </div>
@@ -3449,7 +3449,7 @@ Java supports vectors of unions, but it isn't currently documented.
</div> </div>
<div class="language-csharp"> <div class="language-csharp">
~~~{.cs} ~~~{.cs}
using FlatBuffers; using Google.FlatBuffers;
using Example.VectorOfUnions; using Example.VectorOfUnions;
var fbb = new FlatBufferBuilder(100); var fbb = new FlatBufferBuilder(100);

View File

@@ -0,0 +1,27 @@
# Go Echo Example
A simple example demonstrating how to send flatbuffers over the network in Go.
## Generate flatbuffer code
```
flatc -g --gen-object-api --go-module-name echo hero.fbs net.fbs
```
## Running example
1. Run go mod tidy to get dependencies
```
go mod tidy
```
2. Start a server
```
go run server/server.go
```
3. Run the client in another terminal
```
go run client/client.go
```

View File

@@ -0,0 +1,51 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"echo/hero"
"echo/net"
flatbuffers "github.com/google/flatbuffers/go"
)
func RequestBody() *bytes.Reader {
b := flatbuffers.NewBuilder(0)
r := net.RequestT{Player: &hero.WarriorT{Name: "Krull", Hp: 100}}
b.Finish(r.Pack(b))
return bytes.NewReader(b.FinishedBytes())
}
func ReadResponse(r *http.Response) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Printf("Unable to read request body: %v\n", err)
return
}
res := net.GetRootAsResponse(body, 0)
player := res.Player(nil)
fmt.Printf("Got response (name: %v, hp: %v)\n", string(player.Name()), player.Hp())
}
func main() {
body := RequestBody()
req, err := http.NewRequest("POST", "http://localhost:8080/echo", body)
if err != nil {
fmt.Println(err)
return
}
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
ReadResponse(resp)
}

5
examples/go-echo/go.mod Normal file
View File

@@ -0,0 +1,5 @@
module echo
go 1.19
require github.com/google/flatbuffers v22.10.26+incompatible

View File

@@ -0,0 +1,6 @@
namespace hero;
table Warrior {
name: string;
hp: uint32;
}

View File

@@ -0,0 +1,93 @@
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package hero
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type WarriorT struct {
Name string `json:"name"`
Hp uint32 `json:"hp"`
}
func (t *WarriorT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil { return 0 }
nameOffset := builder.CreateString(t.Name)
WarriorStart(builder)
WarriorAddName(builder, nameOffset)
WarriorAddHp(builder, t.Hp)
return WarriorEnd(builder)
}
func (rcv *Warrior) UnPackTo(t *WarriorT) {
t.Name = string(rcv.Name())
t.Hp = rcv.Hp()
}
func (rcv *Warrior) UnPack() *WarriorT {
if rcv == nil { return nil }
t := &WarriorT{}
rcv.UnPackTo(t)
return t
}
type Warrior struct {
_tab flatbuffers.Table
}
func GetRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Warrior{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &Warrior{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *Warrior) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Warrior) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Warrior) Name() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *Warrior) Hp() uint32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetUint32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *Warrior) MutateHp(n uint32) bool {
return rcv._tab.MutateUint32Slot(6, n)
}
func WarriorStart(builder *flatbuffers.Builder) {
builder.StartObject(2)
}
func WarriorAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
}
func WarriorAddHp(builder *flatbuffers.Builder, hp uint32) {
builder.PrependUint32Slot(1, hp, 0)
}
func WarriorEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

11
examples/go-echo/net.fbs Normal file
View File

@@ -0,0 +1,11 @@
include "hero.fbs";
namespace net;
table Request {
player: hero.Warrior;
}
table Response {
player: hero.Warrior;
}

View File

@@ -0,0 +1,82 @@
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package net
import (
flatbuffers "github.com/google/flatbuffers/go"
hero "echo/hero"
)
type RequestT struct {
Player *hero.WarriorT `json:"player"`
}
func (t *RequestT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil { return 0 }
playerOffset := t.Player.Pack(builder)
RequestStart(builder)
RequestAddPlayer(builder, playerOffset)
return RequestEnd(builder)
}
func (rcv *Request) UnPackTo(t *RequestT) {
t.Player = rcv.Player(nil).UnPack()
}
func (rcv *Request) UnPack() *RequestT {
if rcv == nil { return nil }
t := &RequestT{}
rcv.UnPackTo(t)
return t
}
type Request struct {
_tab flatbuffers.Table
}
func GetRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Request{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &Request{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *Request) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Request) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Request) Player(obj *hero.Warrior) *hero.Warrior {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(hero.Warrior)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
func RequestStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func RequestAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0)
}
func RequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -0,0 +1,82 @@
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package net
import (
flatbuffers "github.com/google/flatbuffers/go"
hero "echo/hero"
)
type ResponseT struct {
Player *hero.WarriorT `json:"player"`
}
func (t *ResponseT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil { return 0 }
playerOffset := t.Player.Pack(builder)
ResponseStart(builder)
ResponseAddPlayer(builder, playerOffset)
return ResponseEnd(builder)
}
func (rcv *Response) UnPackTo(t *ResponseT) {
t.Player = rcv.Player(nil).UnPack()
}
func (rcv *Response) UnPack() *ResponseT {
if rcv == nil { return nil }
t := &ResponseT{}
rcv.UnPackTo(t)
return t
}
type Response struct {
_tab flatbuffers.Table
}
func GetRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Response{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &Response{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *Response) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Response) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Response) Player(obj *hero.Warrior) *hero.Warrior {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(hero.Warrior)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
func ResponseStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func ResponseAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0)
}
func ResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -0,0 +1,29 @@
package main
import (
"echo/net"
"fmt"
"io/ioutil"
"net/http"
)
func echo(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Printf("Unable to read request body: %v\n", err)
return
}
req := net.GetRootAsRequest(body, 0)
player := req.Player(nil)
fmt.Printf("Got request (name: %v, hp: %v)\n", string(player.Name()), player.Hp())
w.Write(body)
}
func main() {
http.HandleFunc("/echo", echo)
fmt.Println("Listening on port :8080")
http.ListenAndServe(":8080", nil)
}

View File

@@ -1,5 +1,7 @@
package flatbuffers package flatbuffers
import "sort"
// Builder is a state machine for creating FlatBuffer objects. // Builder is a state machine for creating FlatBuffer objects.
// Use a Builder to construct object(s) starting from leaf nodes. // Use a Builder to construct object(s) starting from leaf nodes.
// //
@@ -315,6 +317,25 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
return b.Offset() return b.Offset()
} }
// CreateVectorOfTables serializes slice of table offsets into a vector.
func (b *Builder) CreateVectorOfTables(offsets []UOffsetT) UOffsetT {
b.assertNotNested()
b.StartVector(4, len(offsets), 4)
for i := len(offsets) - 1; i >= 0; i-- {
b.PrependUOffsetT(offsets[i])
}
return b.EndVector(len(offsets))
}
type KeyCompare func(o1, o2 UOffsetT, buf []byte) bool
func (b *Builder) CreateVectorOfSortedTables(offsets []UOffsetT, keyCompare KeyCompare) UOffsetT {
sort.Slice(offsets, func(i, j int) bool {
return keyCompare(offsets[i], offsets[j], b.Bytes)
})
return b.CreateVectorOfTables(offsets)
}
// CreateSharedString Checks if the string is already written // CreateSharedString Checks if the string is already written
// to the buffer before calling CreateString // to the buffer before calling CreateString
func (b *Builder) CreateSharedString(s string) UOffsetT { func (b *Builder) CreateSharedString(s string) UOffsetT {

3
go/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module github.com/google/flatbuffers/go
go 1.19

View File

@@ -23,3 +23,8 @@ func GetSizePrefixedRootAs(buf []byte, offset UOffsetT, fb FlatBuffer) {
func GetSizePrefix(buf []byte, offset UOffsetT) uint32 { func GetSizePrefix(buf []byte, offset UOffsetT) uint32 {
return GetUint32(buf[offset:]) return GetUint32(buf[offset:])
} }
// GetIndirectOffset retrives the relative offset in the provided buffer stored at `offset`.
func GetIndirectOffset(buf []byte, offset UOffsetT) UOffsetT {
return offset + GetUOffsetT(buf[offset:])
}

View File

@@ -6,7 +6,7 @@ import FlatBuffers
public struct models_HelloReply: FlatBufferObject, Verifiable { public struct models_HelloReply: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_22_9_24() } static func validateVersion() { FlatBuffersVersion_23_1_4() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table
@@ -55,7 +55,7 @@ extension models_HelloReply: Encodable {
public struct models_HelloRequest: FlatBufferObject, Verifiable { public struct models_HelloRequest: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_22_9_24() } static func validateVersion() { FlatBuffersVersion_23_1_4() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table

View File

@@ -65,4 +65,4 @@ class Allocator {
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_ALLOCATOR_H_ #endif // FLATBUFFERS_ALLOCATOR_H_

View File

@@ -35,7 +35,7 @@ template<typename T, uint16_t length> class Array {
public: public:
typedef uint16_t size_type; typedef uint16_t size_type;
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type; typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
typedef VectorIterator<T, return_type> const_iterator; typedef VectorConstIterator<T, return_type> const_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator; typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
// If T is a LE-scalar or a struct (!scalar_tag::value). // If T is a LE-scalar or a struct (!scalar_tag::value).

View File

@@ -32,7 +32,7 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) #if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__)
#include <utility.h> #include <utility.h>
#else #else
#include <utility> #include <utility>
@@ -138,9 +138,9 @@
#endif #endif
#endif // !defined(FLATBUFFERS_LITTLEENDIAN) #endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 22 #define FLATBUFFERS_VERSION_MAJOR 23
#define FLATBUFFERS_VERSION_MINOR 9 #define FLATBUFFERS_VERSION_MINOR 1
#define FLATBUFFERS_VERSION_REVISION 24 #define FLATBUFFERS_VERSION_REVISION 4
#define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers { namespace flatbuffers {

View File

@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_BUFFER_H_ #ifndef FLATBUFFERS_BUFFER_H_
#define FLATBUFFERS_BUFFER_H_ #define FLATBUFFERS_BUFFER_H_
#include <algorithm>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
namespace flatbuffers { namespace flatbuffers {
@@ -76,6 +78,9 @@ template<typename T> struct IndirectHelper {
static return_type Read(const uint8_t *p, uoffset_t i) { static return_type Read(const uint8_t *p, uoffset_t i) {
return EndianScalar((reinterpret_cast<const T *>(p))[i]); return EndianScalar((reinterpret_cast<const T *>(p))[i]);
} }
static return_type Read(uint8_t *p, uoffset_t i) {
return Read(const_cast<const uint8_t *>(p), i);
}
}; };
template<typename T> struct IndirectHelper<Offset<T>> { template<typename T> struct IndirectHelper<Offset<T>> {
typedef const T *return_type; typedef const T *return_type;
@@ -85,13 +90,20 @@ template<typename T> struct IndirectHelper<Offset<T>> {
p += i * sizeof(uoffset_t); p += i * sizeof(uoffset_t);
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p)); return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
} }
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
p += i * sizeof(uoffset_t);
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p));
}
}; };
template<typename T> struct IndirectHelper<const T *> { template<typename T> struct IndirectHelper<const T *> {
typedef const T *return_type; typedef const T *return_type;
typedef T *mutable_return_type; typedef T *mutable_return_type;
static const size_t element_stride = sizeof(T); static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) { static return_type Read(const uint8_t *p, uoffset_t i) {
return reinterpret_cast<const T *>(p + i * sizeof(T)); return reinterpret_cast<return_type>(p + i * sizeof(T));
}
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T));
} }
}; };
@@ -139,4 +151,4 @@ template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_BUFFER_H_ #endif // FLATBUFFERS_BUFFER_H_

View File

@@ -50,4 +50,4 @@ template<typename T> struct BufferRef : BufferRefBase {
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_BUFFER_REF_H_ #endif // FLATBUFFERS_BUFFER_REF_H_

View File

@@ -61,4 +61,4 @@ inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_ #endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_

View File

@@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_ #ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_
#define FLATBUFFERS_FLATBUFFER_BUILDER_H_ #define FLATBUFFERS_FLATBUFFER_BUILDER_H_
#include <algorithm>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>

View File

@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_H_ #ifndef FLATBUFFERS_H_
#define FLATBUFFERS_H_ #define FLATBUFFERS_H_
#include <algorithm>
// TODO: These includes are for mitigating the pains of users editing their // TODO: These includes are for mitigating the pains of users editing their
// source because they relied on flatbuffers.h to include everything for them. // source because they relied on flatbuffers.h to include everything for them.
#include "flatbuffers/array.h" #include "flatbuffers/array.h"

View File

@@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_FLEXBUFFERS_H_ #ifndef FLATBUFFERS_FLEXBUFFERS_H_
#define FLATBUFFERS_FLEXBUFFERS_H_ #define FLATBUFFERS_FLEXBUFFERS_H_
#include <algorithm>
#include <map> #include <map>
// Used to select STL variant. // Used to select STL variant.
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
@@ -382,10 +383,10 @@ class Reference {
type_(type) {} type_(type) {}
Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type) Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
: data_(data), parent_width_(parent_width) { : data_(data),
byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3); parent_width_(parent_width),
type_ = static_cast<Type>(packed_type >> 2); byte_width_(static_cast<uint8_t>(1 << (packed_type & 3))),
} type_(static_cast<Type>(packed_type >> 2)) {}
Type GetType() const { return type_; } Type GetType() const { return type_; }

View File

@@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_IDL_H_ #ifndef FLATBUFFERS_IDL_H_
#define FLATBUFFERS_IDL_H_ #define FLATBUFFERS_IDL_H_
#include <algorithm>
#include <functional> #include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
@@ -382,7 +383,14 @@ struct EnumVal {
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const; const Parser &parser) const;
bool Deserialize(const Parser &parser, const reflection::EnumVal *val); bool Deserialize(Parser &parser, const reflection::EnumVal *val);
flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
bool DeserializeAttributes(Parser &parser,
const Vector<Offset<reflection::KeyValue>> *attrs);
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); } uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
int64_t GetAsInt64() const { return value; } int64_t GetAsInt64() const { return value; }
@@ -392,6 +400,7 @@ struct EnumVal {
std::string name; std::string name;
std::vector<std::string> doc_comment; std::vector<std::string> doc_comment;
Type union_type; Type union_type;
SymbolTable<Value> attributes;
private: private:
friend EnumDef; friend EnumDef;
@@ -464,6 +473,10 @@ inline bool IsStruct(const Type &type) {
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
} }
inline bool IsIncompleteStruct(const Type &type) {
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->predecl;
}
inline bool IsTable(const Type &type) { inline bool IsTable(const Type &type) {
return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed; return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
} }
@@ -480,11 +493,11 @@ inline bool IsVector(const Type &type) {
return type.base_type == BASE_TYPE_VECTOR; return type.base_type == BASE_TYPE_VECTOR;
} }
inline bool IsVectorOfStruct(const Type& type) { inline bool IsVectorOfStruct(const Type &type) {
return IsVector(type) && IsStruct(type.VectorType()); return IsVector(type) && IsStruct(type.VectorType());
} }
inline bool IsVectorOfTable(const Type& type) { inline bool IsVectorOfTable(const Type &type) {
return IsVector(type) && IsTable(type.VectorType()); return IsVector(type) && IsTable(type.VectorType());
} }
@@ -528,8 +541,11 @@ inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
inline bool EqualByName(const Type &a, const Type &b) { inline bool EqualByName(const Type &a, const Type &b) {
return a.base_type == b.base_type && a.element == b.element && return a.base_type == b.base_type && a.element == b.element &&
(a.struct_def == b.struct_def || (a.struct_def == b.struct_def ||
a.struct_def->name == b.struct_def->name) && (a.struct_def != nullptr && b.struct_def != nullptr &&
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name); a.struct_def->name == b.struct_def->name)) &&
(a.enum_def == b.enum_def ||
(a.enum_def != nullptr && b.enum_def != nullptr &&
a.enum_def->name == b.enum_def->name));
} }
struct RPCCall : public Definition { struct RPCCall : public Definition {
@@ -578,6 +594,7 @@ struct IDLOptions {
bool strict_json; bool strict_json;
bool output_default_scalars_in_json; bool output_default_scalars_in_json;
int indent_step; int indent_step;
bool cpp_minify_enums;
bool output_enum_identifiers; bool output_enum_identifiers;
bool prefixed_enums; bool prefixed_enums;
bool scoped_enums; bool scoped_enums;
@@ -613,6 +630,7 @@ struct IDLOptions {
bool binary_schema_gen_embed; bool binary_schema_gen_embed;
std::string go_import; std::string go_import;
std::string go_namespace; std::string go_namespace;
std::string go_module_name;
bool protobuf_ascii_alike; bool protobuf_ascii_alike;
bool size_prefixed; bool size_prefixed;
std::string root_type; std::string root_type;
@@ -634,6 +652,7 @@ struct IDLOptions {
bool json_nested_legacy_flatbuffers; bool json_nested_legacy_flatbuffers;
bool ts_flat_file; bool ts_flat_file;
bool no_leak_private_annotations; bool no_leak_private_annotations;
bool require_json_eof;
// Possible options for the more general generator below. // Possible options for the more general generator below.
enum Language { enum Language {
@@ -653,6 +672,7 @@ struct IDLOptions {
kRust = 1 << 14, kRust = 1 << 14,
kKotlin = 1 << 15, kKotlin = 1 << 15,
kSwift = 1 << 16, kSwift = 1 << 16,
kNim = 1 << 17,
kMAX kMAX
}; };
@@ -687,6 +707,7 @@ struct IDLOptions {
strict_json(false), strict_json(false),
output_default_scalars_in_json(false), output_default_scalars_in_json(false),
indent_step(2), indent_step(2),
cpp_minify_enums(false),
output_enum_identifiers(true), output_enum_identifiers(true),
prefixed_enums(true), prefixed_enums(true),
scoped_enums(false), scoped_enums(false),
@@ -734,6 +755,7 @@ struct IDLOptions {
json_nested_legacy_flatbuffers(false), json_nested_legacy_flatbuffers(false),
ts_flat_file(false), ts_flat_file(false),
no_leak_private_annotations(false), no_leak_private_annotations(false),
require_json_eof(true),
mini_reflect(IDLOptions::kNone), mini_reflect(IDLOptions::kNone),
require_explicit_ids(false), require_explicit_ids(false),
rust_serialize(false), rust_serialize(false),
@@ -746,7 +768,8 @@ struct IDLOptions {
// This encapsulates where the parser is in the current source file. // This encapsulates where the parser is in the current source file.
struct ParserState { struct ParserState {
ParserState() ParserState()
: cursor_(nullptr), : prev_cursor_(nullptr),
cursor_(nullptr),
line_start_(nullptr), line_start_(nullptr),
line_(0), line_(0),
token_(-1), token_(-1),
@@ -754,6 +777,7 @@ struct ParserState {
protected: protected:
void ResetState(const char *source) { void ResetState(const char *source) {
prev_cursor_ = source;
cursor_ = source; cursor_ = source;
line_ = 0; line_ = 0;
MarkNewLine(); MarkNewLine();
@@ -768,7 +792,8 @@ struct ParserState {
FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_); FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
return static_cast<int64_t>(cursor_ - line_start_); return static_cast<int64_t>(cursor_ - line_start_);
} }
const char *prev_cursor_;
const char *cursor_; const char *cursor_;
const char *line_start_; const char *line_start_;
int line_; // the current line being parsed int line_; // the current line being parsed
@@ -896,6 +921,9 @@ class Parser : public ParserState {
bool ParseJson(const char *json, const char *json_filename = nullptr); bool ParseJson(const char *json, const char *json_filename = nullptr);
// Returns the number of characters were consumed when parsing a JSON string.
std::ptrdiff_t BytesConsumed() const;
// Set the root type. May override the one set in the schema. // Set the root type. May override the one set in the schema.
bool SetRootType(const char *name); bool SetRootType(const char *name);
@@ -1016,6 +1044,7 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename); FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
bool isextend, bool inside_oneof); bool isextend, bool inside_oneof);
FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
FLATBUFFERS_CHECKED_ERROR ParseProtoOption(); FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
FLATBUFFERS_CHECKED_ERROR ParseProtoKey(); FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
FLATBUFFERS_CHECKED_ERROR ParseProtoDecl(); FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();

View File

@@ -407,8 +407,9 @@ struct ToStringVisitor : public IterationVisitor {
inline std::string FlatBufferToString(const uint8_t *buffer, inline std::string FlatBufferToString(const uint8_t *buffer,
const TypeTable *type_table, const TypeTable *type_table,
bool multi_line = false, bool multi_line = false,
bool vector_delimited = true) { bool vector_delimited = true,
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "", const std::string& indent = "") {
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, indent,
vector_delimited); vector_delimited);
IterateFlatBuffer(buffer, type_table, &tostring_visitor); IterateFlatBuffer(buffer, type_table, &tostring_visitor);
return tostring_visitor.s; return tostring_visitor.s;

View File

@@ -8,9 +8,9 @@
// Ensure the included flatbuffers.h is the same version as when this file was // Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible. // generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 && static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
FLATBUFFERS_VERSION_MINOR == 9 && FLATBUFFERS_VERSION_MINOR == 1 &&
FLATBUFFERS_VERSION_REVISION == 24, FLATBUFFERS_VERSION_REVISION == 4,
"Non-compatible flatbuffers version included"); "Non-compatible flatbuffers version included");
namespace reflection { namespace reflection {
@@ -265,7 +265,7 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *key() const { const flatbuffers::String *key() const {
return GetPointer<const flatbuffers::String *>(VT_KEY); return GetPointer<const flatbuffers::String *>(VT_KEY);
} }
bool KeyCompareLessThan(const KeyValue *o) const { bool KeyCompareLessThan(const KeyValue * const o) const {
return *key() < *o->key(); return *key() < *o->key();
} }
int KeyCompareWithValue(const char *_key) const { int KeyCompareWithValue(const char *_key) const {
@@ -334,7 +334,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_NAME = 4, VT_NAME = 4,
VT_VALUE = 6, VT_VALUE = 6,
VT_UNION_TYPE = 10, VT_UNION_TYPE = 10,
VT_DOCUMENTATION = 12 VT_DOCUMENTATION = 12,
VT_ATTRIBUTES = 14
}; };
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
@@ -342,7 +343,7 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
int64_t value() const { int64_t value() const {
return GetField<int64_t>(VT_VALUE, 0); return GetField<int64_t>(VT_VALUE, 0);
} }
bool KeyCompareLessThan(const EnumVal *o) const { bool KeyCompareLessThan(const EnumVal * const o) const {
return value() < o->value(); return value() < o->value();
} }
int KeyCompareWithValue(int64_t _value) const { int KeyCompareWithValue(int64_t _value) const {
@@ -354,6 +355,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
} }
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
}
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_NAME) && VerifyOffsetRequired(verifier, VT_NAME) &&
@@ -364,6 +368,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_DOCUMENTATION) && VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.VerifyVector(documentation()) && verifier.VerifyVector(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) && verifier.VerifyVectorOfStrings(documentation()) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
verifier.VerifyVector(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
verifier.EndTable(); verifier.EndTable();
} }
}; };
@@ -384,6 +391,9 @@ struct EnumValBuilder {
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation); fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
} }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
fbb_.AddOffset(EnumVal::VT_ATTRIBUTES, attributes);
}
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) { : fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
@@ -401,9 +411,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::String> name = 0,
int64_t value = 0, int64_t value = 0,
flatbuffers::Offset<reflection::Type> union_type = 0, flatbuffers::Offset<reflection::Type> union_type = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0) {
EnumValBuilder builder_(_fbb); EnumValBuilder builder_(_fbb);
builder_.add_value(value); builder_.add_value(value);
builder_.add_attributes(attributes);
builder_.add_documentation(documentation); builder_.add_documentation(documentation);
builder_.add_union_type(union_type); builder_.add_union_type(union_type);
builder_.add_name(name); builder_.add_name(name);
@@ -415,15 +427,18 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
const char *name = nullptr, const char *name = nullptr,
int64_t value = 0, int64_t value = 0,
flatbuffers::Offset<reflection::Type> union_type = 0, flatbuffers::Offset<reflection::Type> union_type = 0,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr,
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0; auto name__ = name ? _fbb.CreateString(name) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
return reflection::CreateEnumVal( return reflection::CreateEnumVal(
_fbb, _fbb,
name__, name__,
value, value,
union_type, union_type,
documentation__); documentation__,
attributes__);
} }
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -440,7 +455,7 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
} }
bool KeyCompareLessThan(const Enum *o) const { bool KeyCompareLessThan(const Enum * const o) const {
return *name() < *o->name(); return *name() < *o->name();
} }
int KeyCompareWithValue(const char *_name) const { int KeyCompareWithValue(const char *_name) const {
@@ -591,7 +606,7 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
} }
bool KeyCompareLessThan(const Field *o) const { bool KeyCompareLessThan(const Field * const o) const {
return *name() < *o->name(); return *name() < *o->name();
} }
int KeyCompareWithValue(const char *_name) const { int KeyCompareWithValue(const char *_name) const {
@@ -797,7 +812,7 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
} }
bool KeyCompareLessThan(const Object *o) const { bool KeyCompareLessThan(const Object * const o) const {
return *name() < *o->name(); return *name() < *o->name();
} }
int KeyCompareWithValue(const char *_name) const { int KeyCompareWithValue(const char *_name) const {
@@ -949,7 +964,7 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
} }
bool KeyCompareLessThan(const RPCCall *o) const { bool KeyCompareLessThan(const RPCCall * const o) const {
return *name() < *o->name(); return *name() < *o->name();
} }
int KeyCompareWithValue(const char *_name) const { int KeyCompareWithValue(const char *_name) const {
@@ -1065,7 +1080,7 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
} }
bool KeyCompareLessThan(const Service *o) const { bool KeyCompareLessThan(const Service * const o) const {
return *name() < *o->name(); return *name() < *o->name();
} }
int KeyCompareWithValue(const char *_name) const { int KeyCompareWithValue(const char *_name) const {
@@ -1184,7 +1199,7 @@ struct SchemaFile FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *filename() const { const flatbuffers::String *filename() const {
return GetPointer<const flatbuffers::String *>(VT_FILENAME); return GetPointer<const flatbuffers::String *>(VT_FILENAME);
} }
bool KeyCompareLessThan(const SchemaFile *o) const { bool KeyCompareLessThan(const SchemaFile * const o) const {
return *filename() < *o->filename(); return *filename() < *o->filename();
} }
int KeyCompareWithValue(const char *_filename) const { int KeyCompareWithValue(const char *_filename) const {

View File

@@ -61,4 +61,4 @@ static inline flatbuffers::string_view GetStringView(const String *str) {
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_STRING_H_ #endif // FLATBUFFERS_STRING_H_

View File

@@ -50,4 +50,4 @@ class Struct FLATBUFFERS_FINAL_CLASS {
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_STRUCT_H_ #endif // FLATBUFFERS_STRUCT_H_

View File

@@ -31,6 +31,7 @@
# include <stdio.h> # include <stdio.h>
#endif // FLATBUFFERS_PREFER_PRINTF #endif // FLATBUFFERS_PREFER_PRINTF
#include <limits>
#include <string> #include <string>
namespace flatbuffers { namespace flatbuffers {
@@ -392,6 +393,18 @@ inline uint64_t StringToUInt(const char *s, int base = 10) {
return StringToIntegerImpl(&val, s, base) ? val : 0; return StringToIntegerImpl(&val, s, base) ? val : 0;
} }
inline bool StringIsFlatbufferNan(const std::string &s) {
return s == "nan" || s == "+nan" || s == "-nan";
}
inline bool StringIsFlatbufferPositiveInfinity(const std::string &s) {
return s == "inf" || s == "+inf" || s == "infinity" || s == "+infinity";
}
inline bool StringIsFlatbufferNegativeInfinity(const std::string &s) {
return s == "-inf" || s == "-infinity";
}
typedef bool (*LoadFileFunction)(const char *filename, bool binary, typedef bool (*LoadFileFunction)(const char *filename, bool binary,
std::string *dest); std::string *dest);
typedef bool (*FileExistsFunction)(const char *filename); typedef bool (*FileExistsFunction)(const char *filename);

View File

@@ -27,14 +27,15 @@ struct String;
// An STL compatible iterator implementation for Vector below, effectively // An STL compatible iterator implementation for Vector below, effectively
// calling Get() for every element. // calling Get() for every element.
template<typename T, typename IT> struct VectorIterator { template<typename T, typename IT, typename Data = uint8_t *>
struct VectorIterator {
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
typedef IT value_type; typedef IT value_type;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
typedef IT *pointer; typedef IT *pointer;
typedef IT &reference; typedef IT &reference;
VectorIterator(const uint8_t *data, uoffset_t i) VectorIterator(Data data, uoffset_t i)
: data_(data + IndirectHelper<T>::element_stride * i) {} : data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {} VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator() : data_(nullptr) {} VectorIterator() : data_(nullptr) {}
@@ -116,9 +117,12 @@ template<typename T, typename IT> struct VectorIterator {
} }
private: private:
const uint8_t *data_; Data data_;
}; };
template<typename T, typename IT>
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>;
template<typename Iterator> template<typename Iterator>
struct VectorReverseIterator : public std::reverse_iterator<Iterator> { struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
explicit VectorReverseIterator(Iterator iter) explicit VectorReverseIterator(Iterator iter)
@@ -145,7 +149,7 @@ template<typename T> class Vector {
public: public:
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type> typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
iterator; iterator;
typedef VectorIterator<T, typename IndirectHelper<T>::return_type> typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type>
const_iterator; const_iterator;
typedef VectorReverseIterator<iterator> reverse_iterator; typedef VectorReverseIterator<iterator> reverse_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator; typedef VectorReverseIterator<const_iterator> const_reverse_iterator;

View File

@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_ #ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
#define FLATBUFFERS_VECTOR_DOWNWARD_H_ #define FLATBUFFERS_VECTOR_DOWNWARD_H_
#include <algorithm>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
#include "flatbuffers/default_allocator.h" #include "flatbuffers/default_allocator.h"
#include "flatbuffers/detached_buffer.h" #include "flatbuffers/detached_buffer.h"

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId> <groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId> <artifactId>flatbuffers-java</artifactId>
<version>22.9.24</version> <version>23.1.4</version>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<name>FlatBuffers Java API</name> <name>FlatBuffers Java API</name>
<description> <description>
@@ -58,19 +58,17 @@
</distributionManagement> </distributionManagement>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration> <configuration>
<release>8</release> <release>8</release>
<testExcludes> <testExcludes>
<testExclude>**/LongEnum.java</testExclude> <testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude>
<testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude> <testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude>
<testExclude>MyGame/Example/StructOfStructs**</testExclude> </testExcludes>
<testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude> </configuration>
</testExcludes> <version>3.8.1</version>
</configuration> </plugin>
<version>3.8.1</version>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
@@ -149,10 +147,10 @@
<goal>sign</goal> <goal>sign</goal>
</goals> </goals>
<configuration> <configuration>
<gpgArguments> <gpgArguments>
<arg>--pinentry-mode</arg> <arg>--pinentry-mode</arg>
<arg>loopback</arg> <arg>loopback</arg>
</gpgArguments> </gpgArguments>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@@ -173,4 +171,3 @@
</profile> </profile>
</profiles> </profiles>
</project> </project>

View File

@@ -46,7 +46,7 @@ public class Constants {
Changes to the Java implementation need to be sure to change Changes to the Java implementation need to be sure to change
the version here and in the code generator on every possible the version here and in the code generator on every possible
incompatible change */ incompatible change */
public static void FLATBUFFERS_22_9_24() {} public static void FLATBUFFERS_23_1_4() {}
} }
/// @endcond /// @endcond

View File

@@ -32,6 +32,6 @@ namespace Google.FlatBuffers
Changes to the C# implementation need to be sure to change Changes to the C# implementation need to be sure to change
the version here and in the code generator on every possible the version here and in the code generator on every possible
incompatible change */ incompatible change */
public static void FLATBUFFERS_22_9_24() {} public static void FLATBUFFERS_23_1_4() {}
} }
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks> <TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks>
<Description>A cross-platform memory efficient serialization library</Description> <Description>A cross-platform memory efficient serialization library</Description>
<PackageVersion>22.9.24</PackageVersion> <PackageVersion>23.1.4</PackageVersion>
<Authors>Google LLC</Authors> <Authors>Google LLC</Authors>
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl> <PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl> <RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>

7
nim/flatbuffers.nimble Normal file
View File

@@ -0,0 +1,7 @@
version = "2.0.8"
author = "flatbuffers"
description = "Flatbuffers"
license = "Apache 2.0"
srcDir = "flatbuffers"
requires "nim >= 1.4.0"

View File

@@ -0,0 +1,7 @@
import
src/[
builder,
struct,
table
]
export flatbuffers.builder, flatbuffers.table, flatbuffers.struct

View File

@@ -0,0 +1,262 @@
import math
import table
const MAX_BUFFER_SIZE* = 2^31
type Builder* = ref object of RootObj
bytes*: seq[byte]
minalign*: int
current_vtable*: seq[uoffset]
objectEnd*: uoffset
vtables*: seq[uoffset] #?
head*: uoffset
nested*: bool
finished*: bool
vectorNumElems*: uoffset
using this: var Builder
func newBuilder*(size: int): Builder =
result = new Builder
result.bytes.setLen(size)
result.minalign = 1
result.head = size.uoffset
result.nested = false
result.finished = false
result.vectorNumElems = 0
proc FinishedBytes*(this): seq[byte] =
if not this.finished:
quit("Builder not finished, Incorrect use of FinishedBytes(): must call 'Finish' first.")
result = this.bytes[this.head..^1]
proc Output*(this): seq[byte] =
if not this.finished:
quit("Builder not finished, Incorrect use of Output(): must call 'Finish' first.")
result = this.bytes[this.head..^1]
func Offset*(this): uoffset =
result = this.bytes.len.uoffset - this.head
proc StartObject*(this; numfields: int) =
if this.nested:
quit("builder is nested")
this.current_vtable.setLen(numfields)
for i in this.current_vtable.mitems():
i = 0
this.objectEnd = this.Offset()
this.nested = true
proc GrowByteBuffer*(this) =
if this.bytes.len == MAX_BUFFER_SIZE:
quit("flatbuffers: cannot grow buffer beyond 2 gigabytes")
let oldLen = this.bytes.len
var newLen = min(this.bytes.len * 2, MAX_BUFFER_SIZE)
if newLen == 0:
newLen = 1
this.bytes.setLen(newLen)
var j = this.bytes.len - 1
while j >= 0:
if j >= newLen - oldLen:
this.bytes[j] = this.bytes[j - (newLen - oldLen)]
else:
this.bytes[j] = 0
dec(j)
proc Place*[T](this; x: T) =
this.head -= uoffset x.sizeof
WriteVal(this.bytes, this.head, x)
func Pad*(this; n: int) =
for i in 0..<n:
this.Place(0.byte)
proc Prep*(this; size: int; additionalBytes: int) =
if size > this.minalign:
this.minalign = size
var alignsize = (not (this.bytes.len - this.head.int + additionalBytes)) + 1
alignsize = alignsize and (size - 1)
while this.head.int < alignsize + size + additionalBytes:
let oldbufSize = this.bytes.len
this.GrowByteBuffer()
this.head = (this.head.int + this.bytes.len - oldbufSize).uoffset
this.Pad(alignsize)
proc PrependOffsetRelative*[T: Offsets](this; off: T) =
when T is voffset:
this.Prep(T.sizeof, 0)
if not off.uoffset <= this.Offset:
quit("flatbuffers: Offset arithmetic error.")
this.Place(off)
else:
this.Prep(T.sizeof, 0)
if not off.uoffset <= this.Offset:
quit("flatbuffers: Offset arithmetic error.")
let off2: T = this.Offset.T - off + sizeof(T).T
this.Place(off2)
proc Prepend*[T](this; x: T) =
this.Prep(x.sizeof, 0)
this.Place(x)
proc Slot*(this; slotnum: int) =
this.current_vtable[slotnum] = this.Offset
proc PrependSlot*[T](this; o: int; x, d: T) =
if x != d:
when T is uoffset or T is soffset or T is voffset:
this.PrependOffsetRelative(x)
else:
this.Prepend(x)
this.Slot(o)
proc AssertStuctInline(this; obj: uoffset) =
if obj != this.Offset:
quit("flatbuffers: Tried to write a Struct at an Offset that is different from the current Offset of the Builder.")
proc PrependStructSlot*(this; o: int; x: uoffset; d: uoffset) =
if x != d:
this.AssertStuctInline(x)
this.Slot(o)
proc Add*[T](this; n: T) =
this.Prep(T.sizeof, 0)
WriteVal(this.bytes, this.head, n)
proc VtableEqual*(a: seq[uoffset]; objectStart: uoffset; b: seq[byte]): bool =
if a.len * voffset.sizeof != b.len:
return false
var i = 0
while i < a.len:
var seq = b[i * voffset.sizeof..<(i + 1) * voffset.sizeof]
let x = GetVal[voffset](addr seq)
if x == 0 and a[i] == 0:
inc i
continue
let y = objectStart.soffset - a[i].soffset
if x.soffset != y:
return false
inc i
return true
proc WriteVtable*(this): uoffset =
this.PrependOffsetRelative(0.soffset)
let objectOffset = this.Offset
var existingVtable = uoffset 0
var i = this.current_vtable.len - 1
while i >= 0 and this.current_vtable[i] == 0: dec i
this.current_vtable = this.current_vtable[0..i]
for i in countdown(this.vtables.len - 1, 0):
let
vt2Offset: uoffset = this.vtables[i]
vt2Start: int = this.bytes.len - int vt2Offset
var seq = this.bytes[vt2Start..<this.bytes.len]
let
vt2Len = GetVal[voffset](addr seq)
metadata = 2 * voffset.sizeof # VtableMetadataFields * SizeVOffsetT
vt2End = vt2Start + vt2Len.int
vt2 = this.bytes[this.bytes.len - vt2Offset.int + metadata..<vt2End]
if VtableEqual(this.current_vtable, objectOffset, vt2):
existingVtable = vt2Offset
break
if existingVtable == 0:
for i in countdown(this.current_vtable.len - 1, 0):
var off: uoffset
if this.current_vtable[i] != 0:
off = objectOffset - this.current_vtable[i]
this.PrependOffsetRelative(off.voffset)
let objectSize = objectOffset - this.objectEnd
this.PrependOffsetRelative(objectSize.voffset)
let vBytes = (this.current_vtable.len + 2) * voffset.sizeof
this.PrependOffsetRelative(vBytes.voffset)
let objectStart: uoffset = (this.bytes.len.uoffset - objectOffset)
WriteVal(this.bytes, objectStart, (this.Offset - objectOffset).soffset)
this.vtables.add this.Offset
else:
let objectStart: uoffset = this.bytes.len.uoffset - objectOffset
this.head = objectStart
WriteVal(this.bytes, this.head,
(existingVtable.soffset - objectOffset.soffset))
this.current_vtable = @[]
result = objectOffset
proc EndObject*(this): uoffset =
if not this.nested:
quit("builder is not nested")
result = this.WriteVtable()
this.nested = false
proc End*(this: var Builder): uoffset =
result = this.EndObject()
proc StartVector*(this; elemSize: int; numElems: uoffset;
alignment: int) =
if this.nested:
quit("builder is nested")
this.nested = true
this.vectorNumElems = numElems
this.Prep(sizeof(uint32), elemSize * numElems.int)
this.Prep(alignment, elemSize * numElems.int)
proc EndVector*(this): uoffset =
if not this.nested:
quit("builder is not nested")
this.nested = false
this.Place(this.vectorNumElems)
this.vectorNumElems = 0
result = this.Offset
proc getChars*(str: seq[byte]): string =
var bytes = str
result = GetVal[string](addr bytes)
proc getBytes*(str: string | cstring): seq[byte] =
for chr in str:
result.add byte chr
result.add byte 0
proc Create*[T](this; s: T): uoffset = # Both CreateString and CreateByteVector functionality
if this.nested:
quit("builder is nested")
this.nested = true
when T is cstring or T is string:
let x = s.getBytes()
let l = x.len.uoffset
this.vectorNumElems = l-1
else:
let x = s
let l = x.len.uoffset
this.vectorNumElems = l
this.Prep(uoffset.sizeof, l.int * byte.sizeof)
this.head -= l
this.bytes[this.head..<this.head+l] = x
result = this.EndVector()
proc Finish*(this; rootTable: uoffset) =
if this.nested:
quit("builder is nested")
this.nested = true
this.Prep(this.minalign, uoffset.sizeof)
this.PrependOffsetRelative(rootTable)
this.finished = true

View File

@@ -0,0 +1,12 @@
template swapEndian*(outp, inp: pointer, size: int) =
var i = cast[cstring](inp)
var o = cast[cstring](outp)
for x in 0..<size:
o[x] = i[(0..<size).len - x - 1]
when system.cpuEndian == bigEndian:
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
else:
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)

View File

@@ -0,0 +1,24 @@
import table
type FlatObj* {.inheritable.} = object
tab*: Vtable
func Table*(this: var FlatObj): Vtable = this.tab
func Init*(this: var FlatObj; buf: seq[byte]; i: uoffset) =
this.tab.Bytes = buf
this.tab.Pos = i
# Cant define it in table.nim since it needs FlatObj and Init
func GetUnion*[T: FlatObj](this: var Vtable; off: uoffset): T =
result.Init(this.Bytes, this.Indirect(off))
func GetRootAs*(result: var FlatObj; buf: seq[byte]; offset: uoffset) =
var
vtable = Vtable(Bytes: buf[offset..^1], Pos: offset)
n = Get[uoffset](vtable, offset)
result.Init(buf, n+offset)
func GetRootAs*(result: var FlatObj; buf: string; offset: uoffset) =
result.GetRootAs(cast[seq[byte]](buf), offset)

View File

@@ -0,0 +1,149 @@
import endian
type
uoffset* = uint32 ## offset in to the buffer
soffset* = int32 ## offset from start of table, to a vtable
voffset* = uint16 ## offset from start of table to value
type Offsets* = uoffset | soffset | voffset
type Vtable* = object
Bytes*: seq[byte]
Pos*: uoffset
using this: Vtable
func GetVal*[T](b: ptr seq[byte]): T {.inline.} =
when T is float64:
result = cast[T](GetVal[uint64](b))
elif T is float32:
result = cast[T](GetVal[uint32](b))
elif T is string:
result = cast[T](b[])
else:
if b[].len < T.sizeof:
b[].setLen T.sizeof
result = cast[ptr T](unsafeAddr b[][0])[]
template Get*[T](this; off: uoffset): T =
var seq = this.Bytes[off..^1]
GetVal[T](addr seq)
template Get*[T](this; off: soffset): T =
var seq = this.Bytes[off..^1]
GetVal[T](addr seq)
template Get*[T](this; off: voffset): T =
var seq = this.Bytes[off..^1]
GetVal[T](addr seq)
func WriteVal*[T: not SomeFloat](b: var openArray[byte]; off: uoffset;
n: T) {.inline.} =
when sizeof(T) == 8:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 4:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 2:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 1:
b[off] = n.uint8
else:
discard
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
#{.error:"shouldnt appear".}
func WriteVal*[T: not SomeFloat](b: var seq[byte]; off: uoffset;
n: T) {.inline.} =
when sizeof(T) == 8:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 4:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 2:
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
elif sizeof(T) == 1:
b[off] = n.uint8
else:
discard
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
#{.error:"shouldnt appear".}
func WriteVal*[T: SomeFloat](b: var openArray[byte]; off: uoffset;
n: T) {.inline.} =
when T is float64:
WriteVal(b, off, cast[uint64](n))
elif T is float32:
WriteVal(b, off, cast[uint32](n))
func WriteVal*[T: SomeFloat](b: var seq[byte]; off: uoffset; n: T) {.inline.} =
when T is float64:
WriteVal(b, off, cast[uint64](n))
elif T is float32:
WriteVal(b, off, cast[uint32](n))
func Offset*(this; off: voffset): voffset =
let vtable = (this.Pos - this.Get[:uoffset](this.Pos)).voffset
let vtableEnd = this.Get[:voffset](vtable)
if off < vtableEnd:
return this.Get[:voffset](vtable + off)
return 0
func Indirect*(this; off: uoffset): uoffset =
result = off + this.Get[:uoffset](off)
func VectorLen*(this; off: uoffset): int =
var newoff: uoffset = off + this.Pos
newoff += this.Get[:uoffset](newoff)
return this.Get[:uoffset](newoff).int
func Vector*(this; off: uoffset): uoffset =
let newoff: uoffset = off + this.Pos
var x: uoffset = newoff + this.Get[:uoffset](newoff)
x += (uoffset.sizeof).uoffset
result = x
func Union*(this; off: uoffset): Vtable =
let newoff: uoffset = off + this.Pos
result.Pos = newoff + this.Get[:uoffset](newoff)
result.Bytes = this.Bytes
func GetSlot*[T](this; slot: voffset; d: T): T =
let off = this.Offset(slot)
if off == 0:
return d
return this.Get[T](this.Pos + off)
func GetOffsetSlot*[T: Offsets](this; slot: voffset; d: T): T =
let off = this.Offset(slot)
if off == 0:
return d
return off
func ByteVector*(this; off: uoffset): seq[byte] =
let
newoff: uoffset = off + this.Get[:uoffset](off)
start = newoff + (uoffset.sizeof).uoffset
var newseq = this.Bytes[newoff..^1]
let
length = GetVal[uoffset](addr newseq)
result = this.Bytes[start..<start+length]
func String*(this; off: uoffset): string =
var byte_seq = this.ByteVector(off)
result = GetVal[string](addr byte_seq)
using this: var Vtable
proc Mutate*[T](this; off: uoffset; n: T): bool =
WriteVal(this.Bytes, off, n)
return true
func MutateSlot*[T](this; slot: voffset; n: T): bool =
let off: voffset = this.Offset(slot)
if off != 0:
return this.Mutate(this.Pos + off.uoffset, n)
return false

View File

@@ -1,6 +1,6 @@
{ {
"name": "flatbuffers", "name": "flatbuffers",
"version": "22.9.24", "version": "23.1.4",
"description": "Memory Efficient Serialization Library", "description": "Memory Efficient Serialization Library",
"files": [ "files": [
"js/**/*.js", "js/**/*.js",
@@ -17,6 +17,7 @@
}, },
"scripts": { "scripts": {
"test": "npm run compile && cd tests/ts && python3 ./TypeScriptTest.py", "test": "npm run compile && cd tests/ts && python3 ./TypeScriptTest.py",
"lint": "eslint ts",
"compile": "tsc && tsc -p tsconfig.mjs.json && rollup -c", "compile": "tsc && tsc -p tsconfig.mjs.json && rollup -c",
"prepublishOnly": "npm install --only=dev && npm run compile" "prepublishOnly": "npm install --only=dev && npm run compile"
}, },

View File

@@ -486,7 +486,12 @@ class ByteBuffer
} }
private static function validateValue($min, $max, $value, $type, $additional_notes = "") { private static function validateValue($min, $max, $value, $type, $additional_notes = "") {
if(!($min <= $value && $value <= $max)) { if (
!(
($type === "byte" && $min <= ord($value) && ord($value) <= $max) ||
($min <= $value && $value <= $max)
)
) {
throw new \InvalidArgumentException(sprintf("bad number %s for type %s.%s", $value, $type, $additional_notes)); throw new \InvalidArgumentException(sprintf("bad number %s for type %s.%s", $value, $type, $additional_notes));
} }
} }

View File

@@ -14,4 +14,4 @@
# Placeholder, to be updated during the release process # Placeholder, to be updated during the release process
# by the setup.py # by the setup.py
__version__ = u"22.9.24" __version__ = u"23.1.4"

View File

@@ -112,7 +112,8 @@ class Builder(object):
## @cond FLATBUFFERS_INTENRAL ## @cond FLATBUFFERS_INTENRAL
__slots__ = ("Bytes", "current_vtable", "head", "minalign", "objectEnd", __slots__ = ("Bytes", "current_vtable", "head", "minalign", "objectEnd",
"vtables", "nested", "forceDefaults", "finished", "vectorNumElems") "vtables", "nested", "forceDefaults", "finished", "vectorNumElems",
"sharedStrings")
"""Maximum buffer size constant, in bytes. """Maximum buffer size constant, in bytes.
@@ -141,6 +142,7 @@ class Builder(object):
self.vtables = {} self.vtables = {}
self.nested = False self.nested = False
self.forceDefaults = False self.forceDefaults = False
self.sharedStrings = {}
## @endcond ## @endcond
self.finished = False self.finished = False
@@ -405,6 +407,20 @@ class Builder(object):
self.vectorNumElems = None self.vectorNumElems = None
return self.Offset() return self.Offset()
def CreateSharedString(self, s, encoding='utf-8', errors='strict'):
"""
CreateSharedString checks if the string is already written to the buffer
before calling CreateString.
"""
if s in self.sharedStrings:
return self.sharedStrings[s]
off = self.CreateString(s, encoding, errors)
self.sharedStrings[s] = off
return off
def CreateString(self, s, encoding='utf-8', errors='strict'): def CreateString(self, s, encoding='utf-8', errors='strict'):
"""CreateString writes a null-terminated byte string as a vector.""" """CreateString writes a null-terminated byte string as a vector."""

View File

@@ -727,6 +727,15 @@ class Ref:
def IsString(self): def IsString(self):
return self._type is Type.STRING return self._type is Type.STRING
@property
def AsStringBytes(self):
if self.IsString:
return String(self._Indirect(), self._byte_width).Bytes
elif self.IsKey:
return self.AsKeyBytes
else:
raise self._ConvertError(Type.STRING)
@property @property
def AsString(self): def AsString(self):
if self.IsString: if self.IsString:

View File

@@ -73,7 +73,32 @@ class EnumVal(object):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12)) o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
return o == 0 return o == 0
def EnumValStart(builder): builder.StartObject(5) # EnumVal
def Attributes(self, j):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
if o != 0:
x = self._tab.Vector(o)
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
x = self._tab.Indirect(x)
from reflection.KeyValue import KeyValue
obj = KeyValue()
obj.Init(self._tab.Bytes, x)
return obj
return None
# EnumVal
def AttributesLength(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
if o != 0:
return self._tab.VectorLen(o)
return 0
# EnumVal
def AttributesIsNone(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
return o == 0
def EnumValStart(builder): builder.StartObject(6)
def Start(builder): def Start(builder):
return EnumValStart(builder) return EnumValStart(builder)
def EnumValAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0) def EnumValAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
@@ -91,6 +116,12 @@ def AddDocumentation(builder, documentation):
def EnumValStartDocumentationVector(builder, numElems): return builder.StartVector(4, numElems, 4) def EnumValStartDocumentationVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartDocumentationVector(builder, numElems): def StartDocumentationVector(builder, numElems):
return EnumValStartDocumentationVector(builder, numElems) return EnumValStartDocumentationVector(builder, numElems)
def EnumValAddAttributes(builder, attributes): builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
def AddAttributes(builder, attributes):
return EnumValAddAttributes(builder, attributes)
def EnumValStartAttributesVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartAttributesVector(builder, numElems):
return EnumValStartAttributesVector(builder, numElems)
def EnumValEnd(builder): return builder.EndObject() def EnumValEnd(builder): return builder.EndObject()
def End(builder): def End(builder):
return EnumValEnd(builder) return EnumValEnd(builder)

View File

@@ -1,2 +1,6 @@
[bdist_wheel] [bdist_wheel]
universal=1 universal=1
[metadata]
license_files =
../license.txt

View File

@@ -12,54 +12,15 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import fileinput
import os
import re
import sys
from datetime import datetime
from setuptools import setup from setuptools import setup
def _update_version_attr(new_version):
for line in fileinput.input('flatbuffers/_version.py', inplace=True):
if line.startswith('__version__'):
line = re.sub(r'".*"', '"{}"'.format(new_version), line)
sys.stdout.write(line)
def version():
version = os.getenv('VERSION', None)
if version:
# Most git tags are prefixed with 'v' (example: v1.2.3) this is
# never desirable for artifact repositories, so we strip the
# leading 'v' if it's present.
version = version[1:] if version.startswith('v') else version
else:
# Default version is an ISO8601 compiliant datetime. PyPI doesn't allow
# the colon ':' character in its versions, and time is required to allow
# for multiple publications to master in one day. This datetime string
# uses the "basic" ISO8601 format for both its date and time components
# to avoid issues with the colon character (ISO requires that date and
# time components of a date-time string must be uniformly basic or
# extended, which is why the date component does not have dashes.
#
# Publications using datetime versions should only be made from master
# to represent the HEAD moving forward.
version = datetime.utcnow().strftime('%Y%m%d%H%M%S')
print("VERSION environment variable not set, using datetime instead: {}"
.format(version))
_update_version_attr(version)
return version
setup( setup(
name='flatbuffers', name='flatbuffers',
version=version(), version='23.1.4',
license='Apache 2.0', license='Apache 2.0',
author='FlatBuffers Contributors', license_files='../LICENSE.txt',
author_email='me@rwinslow.com', author='Derek Bailey',
author_email='derekbailey@google.com',
url='https://google.github.io/flatbuffers/', url='https://google.github.io/flatbuffers/',
long_description=('Python runtime library for use with the ' long_description=('Python runtime library for use with the '
'`Flatbuffers <https://google.github.io/flatbuffers/>`_ ' '`Flatbuffers <https://google.github.io/flatbuffers/>`_ '
@@ -81,4 +42,4 @@ setup(
'Documentation': 'https://google.github.io/flatbuffers/', 'Documentation': 'https://google.github.io/flatbuffers/',
'Source': 'https://github.com/google/flatbuffers', 'Source': 'https://github.com/google/flatbuffers',
}, },
) )

View File

@@ -2,6 +2,7 @@
=========== ===========
![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master) ![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master)
[![BuildKite status](https://badge.buildkite.com/7979d93bc6279aa539971f271253c65d5e8fe2fe43c90bbb25.svg)](https://buildkite.com/bazel/flatbuffers)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/flatbuffers.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:flatbuffers) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/flatbuffers.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:flatbuffers)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers/badge)](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers/badge)](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers)
[![Join the chat at https://gitter.im/google/flatbuffers](https://badges.gitter.im/google/flatbuffers.svg)](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/google/flatbuffers](https://badges.gitter.im/google/flatbuffers.svg)](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -17,7 +18,7 @@ maximum memory efficiency. It allows you to directly access serialized data with
## Supported operating systems ## Supported operating systems
* Windows * Windows
* MacOS X * macOS
* Linux * Linux
* Android * Android
* And any others with a recent C++ compiler (C++ 11 and newer) * And any others with a recent C++ compiler (C++ 11 and newer)
@@ -39,12 +40,9 @@ Code generation and runtime libraries for many popular languages.
1. PHP 1. PHP
1. Python - [PyPi](https://pypi.org/project/flatbuffers/) 1. Python - [PyPi](https://pypi.org/project/flatbuffers/)
1. Rust - [crates.io](https://crates.io/crates/flatbuffers) 1. Rust - [crates.io](https://crates.io/crates/flatbuffers)
1. Swift 1. Swift - [swiftpackageindex](https://swiftpackageindex.com/google/flatbuffers)
1. TypeScript - [NPM](https://www.npmjs.com/package/flatbuffers) 1. TypeScript - [NPM](https://www.npmjs.com/package/flatbuffers)
1. Nim
*and more in progress...*
1. [Nim](https://github.com/google/flatbuffers/pull/7362)
## Contribution ## Contribution

View File

@@ -56,6 +56,7 @@ table EnumVal {
object:Object (deprecated); object:Object (deprecated);
union_type:Type; union_type:Type;
documentation:[string]; documentation:[string];
attributes:[KeyValue];
} }
table Enum { table Enum {

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "flatbuffers" name = "flatbuffers"
version = "2.1.2" version = "23.1.4"
edition = "2018" edition = "2018"
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"] authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
license = "Apache-2.0" license = "Apache-2.0"
@@ -12,15 +12,13 @@ categories = ["encoding", "data-structures", "memory-management"]
rust = "1.51" rust = "1.51"
[features] [features]
default = ["thiserror"] default = ["std"]
no_std = ["core2", "thiserror_core2"] std = []
serialize = ["serde"] serialize = ["serde"]
[dependencies] [dependencies]
smallvec = "1.6.1"
bitflags = "1.2.1" bitflags = "1.2.1"
serde = { version = "1.0", optional = true } serde = { version = "1.0", optional = true }
thiserror = { version = "1.0.30", optional = true }
core2 = { version = "0.4.0", optional = true } [build-dependencies]
# This version is compliant with mainline 1.0.30 rustc_version = "0.4.0"
thiserror_core2 = { version = "2.0.0", default-features = false, optional = true }

12
rust/flatbuffers/build.rs Normal file
View File

@@ -0,0 +1,12 @@
use rustc_version::{version_meta, Channel};
fn main() {
let version_meta = version_meta().unwrap();
// To use nightly features we declare this and then we can use
// #[cfg(nightly)]
// for nightly only features
if version_meta.channel == Channel::Nightly {
println!("cargo:rustc-cfg=nightly")
}
}

View File

@@ -37,14 +37,18 @@ where
#[allow(clippy::len_without_is_empty)] #[allow(clippy::len_without_is_empty)]
#[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into. #[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
impl<'a, T: 'a, const N: usize> Array<'a, T, N> { impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
/// # Safety
///
/// buf must be a contiguous array of `T`
///
/// # Panics
///
/// Panics if `buf.len()` is not `size_of::<T>() * N`
#[inline(always)] #[inline(always)]
pub fn new(buf: &'a [u8]) -> Self { pub unsafe fn new(buf: &'a [u8]) -> Self {
assert!(size_of::<T>() * N == buf.len()); assert_eq!(size_of::<T>() * N, buf.len());
Array { Array(buf, PhantomData)
0: buf,
1: PhantomData,
}
} }
#[inline(always)] #[inline(always)]
@@ -61,34 +65,39 @@ impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
pub fn get(&self, idx: usize) -> T::Inner { pub fn get(&self, idx: usize) -> T::Inner {
assert!(idx < N); assert!(idx < N);
let sz = size_of::<T>(); let sz = size_of::<T>();
T::follow(self.0, sz * idx) // Safety:
// self.0 was valid for length `N` on construction and have verified `idx < N`
unsafe { T::follow(self.0, sz * idx) }
} }
#[inline(always)] #[inline(always)]
pub fn iter(&self) -> VectorIter<'a, T> { pub fn iter(&self) -> VectorIter<'a, T> {
VectorIter::from_slice(self.0, self.len()) // Safety:
// self.0 was valid for length N on construction
unsafe { VectorIter::from_slice(self.0, self.len()) }
} }
} }
impl<'a, T: Follow<'a> + Debug, const N: usize> Into<[T::Inner; N]> for Array<'a, T, N> { impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
#[inline(always)] fn from(array: Array<'a, T, N>) -> Self {
fn into(self) -> [T::Inner; N] { array_init(|i| array.get(i))
array_init(|i| self.get(i))
} }
} }
// TODO(caspern): Implement some future safe version of SafeSliceAccess.
/// Implement Follow for all possible Arrays that have Follow-able elements. /// Implement Follow for all possible Arrays that have Follow-able elements.
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> { impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
type Inner = Array<'a, T, N>; type Inner = Array<'a, T, N>;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Array::new(&buf[loc..loc + N * size_of::<T>()]) Array::new(&buf[loc..loc + N * size_of::<T>()])
} }
} }
pub fn emplace_scalar_array<T: EndianScalar, const N: usize>( /// Place an array of EndianScalar into the provided mutable byte slice. Performs
/// endian conversion, if necessary.
/// # Safety
/// Caller must ensure `s.len() >= size_of::<[T; N]>()`
pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
buf: &mut [u8], buf: &mut [u8],
loc: usize, loc: usize,
src: &[T; N], src: &[T; N],
@@ -96,14 +105,12 @@ pub fn emplace_scalar_array<T: EndianScalar, const N: usize>(
let mut buf_ptr = buf[loc..].as_mut_ptr(); let mut buf_ptr = buf[loc..].as_mut_ptr();
for item in src.iter() { for item in src.iter() {
let item_le = item.to_little_endian(); let item_le = item.to_little_endian();
unsafe { core::ptr::copy_nonoverlapping(
core::ptr::copy_nonoverlapping( &item_le as *const T::Scalar as *const u8,
&item_le as *const T as *const u8, buf_ptr,
buf_ptr, size_of::<T::Scalar>(),
size_of::<T>(), );
); buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
buf_ptr = buf_ptr.add(size_of::<T>());
}
} }
} }
@@ -124,6 +131,8 @@ where
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
let mut ptr_i = array.as_mut_ptr() as *mut T; let mut ptr_i = array.as_mut_ptr() as *mut T;
// Safety:
// array is aligned by T, and has length N
unsafe { unsafe {
for i in 0..N { for i in 0..N {
let value_i = initializer(i); let value_i = initializer(i);
@@ -134,7 +143,7 @@ where
} }
} }
#[cfg(feature="serialize")] #[cfg(feature = "serialize")]
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N> impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
where where
T: 'a + Follow<'a>, T: 'a + Follow<'a>,

View File

@@ -14,26 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
extern crate smallvec; #[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
use core::cmp::max; use core::cmp::max;
use core::iter::{DoubleEndedIterator, ExactSizeIterator}; use core::iter::{DoubleEndedIterator, ExactSizeIterator};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ptr::write_bytes; use core::ptr::write_bytes;
use core::slice::from_raw_parts;
#[cfg(feature = "no_std")]
use alloc::{vec, vec::Vec};
use crate::endian_scalar::{emplace_scalar, read_scalar_at}; use crate::endian_scalar::emplace_scalar;
use crate::primitives::*; use crate::primitives::*;
use crate::push::{Push, PushAlignment}; use crate::push::{Push, PushAlignment};
use crate::read_scalar;
use crate::table::Table; use crate::table::Table;
use crate::vector::{SafeSliceAccess, Vector}; use crate::vector::Vector;
use crate::vtable::{field_index_to_field_offset, VTable}; use crate::vtable::{field_index_to_field_offset, VTable};
use crate::vtable_writer::VTableWriter; use crate::vtable_writer::VTableWriter;
pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16;
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct FieldLoc { struct FieldLoc {
off: UOffsetT, off: UOffsetT,
@@ -120,7 +116,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
// memset only the part of the buffer that could be dirty: // memset only the part of the buffer that could be dirty:
{ {
let to_clear = self.owned_buf.len() - self.head; let to_clear = self.owned_buf.len() - self.head;
let ptr = (&mut self.owned_buf[self.head..]).as_mut_ptr(); let ptr = self.owned_buf[self.head..].as_mut_ptr();
// Safety:
// Verified ptr is valid for `to_clear` above
unsafe { unsafe {
write_bytes(ptr, 0, to_clear); write_bytes(ptr, 0, to_clear);
} }
@@ -152,8 +150,10 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
self.align(sz, P::alignment()); self.align(sz, P::alignment());
self.make_space(sz); self.make_space(sz);
{ {
let (dst, rest) = (&mut self.owned_buf[self.head..]).split_at_mut(sz); let (dst, rest) = self.owned_buf[self.head..].split_at_mut(sz);
x.push(dst, rest); // Safety:
// Called make_space above
unsafe { x.push(dst, rest.len()) };
} }
WIPOffset::new(self.used_space() as UOffsetT) WIPOffset::new(self.used_space() as UOffsetT)
} }
@@ -309,73 +309,32 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
WIPOffset::new(self.used_space() as UOffsetT) WIPOffset::new(self.used_space() as UOffsetT)
} }
/// Create a vector by memcpy'ing. This is much faster than calling
/// `create_vector`, but the underlying type must be represented as
/// little-endian on the host machine. This property is encoded in the
/// type system through the SafeSliceAccess trait. The following types are
/// always safe, on any platform: bool, u8, i8, and any
/// FlatBuffers-generated struct.
#[inline]
pub fn create_vector_direct<'a: 'b, 'b, T: SafeSliceAccess + Push + Sized + 'b>(
&'a mut self,
items: &'b [T],
) -> WIPOffset<Vector<'fbb, T>> {
self.assert_not_nested(
"create_vector_direct can not be called when a table or vector is under construction",
);
let elem_size = T::size();
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
let bytes = {
let ptr = items.as_ptr() as *const T as *const u8;
unsafe { from_raw_parts(ptr, items.len() * elem_size) }
};
self.push_bytes_unprefixed(bytes);
self.push(items.len() as UOffsetT);
WIPOffset::new(self.used_space() as UOffsetT)
}
/// Create a vector of strings.
///
/// Speed-sensitive users may wish to reduce memory usage by creating the
/// vector manually: use `start_vector`, `push`, and `end_vector`.
#[inline]
pub fn create_vector_of_strings<'a, 'b>(
&'a mut self,
xs: &'b [&'b str],
) -> WIPOffset<Vector<'fbb, ForwardsUOffset<&'fbb str>>> {
self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction");
// internally, smallvec can be a stack-allocated or heap-allocated vector:
// if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap.
let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> =
smallvec::SmallVec::with_capacity(xs.len());
unsafe {
offsets.set_len(xs.len());
}
// note that this happens in reverse, because the buffer is built back-to-front:
for (i, &s) in xs.iter().enumerate().rev() {
let o = self.create_string(s);
offsets[i] = o;
}
self.create_vector(&offsets[..])
}
/// Create a vector of Push-able objects. /// Create a vector of Push-able objects.
/// ///
/// Speed-sensitive users may wish to reduce memory usage by creating the /// Speed-sensitive users may wish to reduce memory usage by creating the
/// vector manually: use `start_vector`, `push`, and `end_vector`. /// vector manually: use `start_vector`, `push`, and `end_vector`.
#[inline] #[inline]
pub fn create_vector<'a: 'b, 'b, T: Push + Copy + 'b>( pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
&'a mut self, &'a mut self,
items: &'b [T], items: &'b [T],
) -> WIPOffset<Vector<'fbb, T::Output>> { ) -> WIPOffset<Vector<'fbb, T::Output>> {
let elem_size = T::size(); let elem_size = T::size();
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET)); let slice_size = items.len() * elem_size;
for i in (0..items.len()).rev() { self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET));
self.push(items[i]); self.ensure_capacity(slice_size + UOffsetT::size());
self.head -= slice_size;
let mut written_len = self.owned_buf.len() - self.head;
let buf = &mut self.owned_buf[self.head..self.head + slice_size];
for (item, out) in items.iter().zip(buf.chunks_exact_mut(elem_size)) {
written_len -= elem_size;
// Safety:
// Called ensure_capacity and aligned to T above
unsafe { item.push(out, written_len) };
} }
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value()) WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
} }
@@ -384,17 +343,18 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
/// Speed-sensitive users may wish to reduce memory usage by creating the /// Speed-sensitive users may wish to reduce memory usage by creating the
/// vector manually: use `start_vector`, `push`, and `end_vector`. /// vector manually: use `start_vector`, `push`, and `end_vector`.
#[inline] #[inline]
pub fn create_vector_from_iter<T: Push + Copy>( pub fn create_vector_from_iter<T: Push>(
&mut self, &mut self,
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator, items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
) -> WIPOffset<Vector<'fbb, T::Output>> { ) -> WIPOffset<Vector<'fbb, T::Output>> {
let elem_size = T::size(); let elem_size = T::size();
let len = items.len(); self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
self.align(len * elem_size, T::alignment().max_of(SIZE_UOFFSET)); let mut actual = 0;
for item in items.rev() { for item in items.rev() {
self.push(item); self.push(item);
actual += 1;
} }
WIPOffset::new(self.push::<UOffsetT>(len as UOffsetT).value()) WIPOffset::new(self.push::<UOffsetT>(actual).value())
} }
/// Set whether default values are stored. /// Set whether default values are stored.
@@ -443,7 +403,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
assert_msg_name: &'static str, assert_msg_name: &'static str,
) { ) {
let idx = self.used_space() - tab_revloc.value() as usize; let idx = self.used_space() - tab_revloc.value() as usize;
let tab = Table::new(&self.owned_buf[self.head..], idx);
// Safety:
// The value of TableFinishedWIPOffset is the offset from the end of owned_buf
// to an SOffsetT pointing to a valid VTable
//
// `self.owned_buf.len() = self.used_space() + self.head`
// `self.owned_buf.len() - tab_revloc = self.used_space() - tab_revloc + self.head`
// `self.owned_buf.len() - tab_revloc = idx + self.head`
let tab = unsafe { Table::new(&self.owned_buf[self.head..], idx) };
let o = tab.vtable().get(slot_byte_loc) as usize; let o = tab.vtable().get(slot_byte_loc) as usize;
assert!(o != 0, "missing required field {}", assert_msg_name); assert!(o != 0, "missing required field {}", assert_msg_name);
} }
@@ -560,11 +528,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
} }
} }
let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos]; let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos];
let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| { let found = self
let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize; .written_vtable_revpos
let old_vtable = VTable::init(&self.owned_buf, old_vtable_pos); .binary_search_by(|old_vtable_revpos: &UOffsetT| {
new_vt_bytes.cmp(old_vtable.as_bytes()) let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize;
}); // Safety:
// Already written vtables are valid by construction
let old_vtable = unsafe { VTable::init(&self.owned_buf, old_vtable_pos) };
new_vt_bytes.cmp(old_vtable.as_bytes())
});
let final_vtable_revpos = match found { let final_vtable_revpos = match found {
Ok(i) => { Ok(i) => {
// The new vtable is a duplicate so clear it. // The new vtable is a duplicate so clear it.
@@ -581,12 +553,22 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
}; };
// Write signed offset from table to its vtable. // Write signed offset from table to its vtable.
let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize; let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize;
let tmp_soffset_to_vt = unsafe { read_scalar_at::<UOffsetT>(&self.owned_buf, table_pos) }; if cfg!(debug_assertions) {
debug_assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0); // Safety:
// Verified slice length
let tmp_soffset_to_vt = unsafe {
read_scalar::<UOffsetT>(&self.owned_buf[table_pos..table_pos + SIZE_UOFFSET])
};
assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
}
let buf = &mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET];
// Safety:
// Verified length of buf above
unsafe { unsafe {
emplace_scalar::<SOffsetT>( emplace_scalar::<SOffsetT>(
&mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET], buf,
final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT,
); );
} }
@@ -623,7 +605,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
} }
// finally, zero out the old end data. // finally, zero out the old end data.
{ {
let ptr = (&mut self.owned_buf[..middle]).as_mut_ptr(); let ptr = self.owned_buf[..middle].as_mut_ptr();
// Safety:
// ptr is byte aligned and of length middle
unsafe { unsafe {
write_bytes(ptr, 0, middle); write_bytes(ptr, 0, middle);
} }

View File

@@ -17,6 +17,24 @@
use core::mem::size_of; use core::mem::size_of;
mod private {
/// Types that are trivially transmutable are those where any combination of bits
/// represents a valid value of that type
///
/// For example integral types are TriviallyTransmutable as all bit patterns are valid,
/// however, `bool` is not trivially transmutable as only `0` and `1` are valid
pub trait TriviallyTransmutable {}
impl TriviallyTransmutable for i8 {}
impl TriviallyTransmutable for i16 {}
impl TriviallyTransmutable for i32 {}
impl TriviallyTransmutable for i64 {}
impl TriviallyTransmutable for u8 {}
impl TriviallyTransmutable for u16 {}
impl TriviallyTransmutable for u32 {}
impl TriviallyTransmutable for u64 {}
}
/// Trait for values that must be stored in little-endian byte order, but /// Trait for values that must be stored in little-endian byte order, but
/// might be represented in memory as big-endian. Every type that implements /// might be represented in memory as big-endian. Every type that implements
/// EndianScalar is a valid FlatBuffers scalar value. /// EndianScalar is a valid FlatBuffers scalar value.
@@ -28,144 +46,118 @@ use core::mem::size_of;
/// "too much". For example, num-traits provides i128 support, but that is an /// "too much". For example, num-traits provides i128 support, but that is an
/// invalid FlatBuffers type. /// invalid FlatBuffers type.
pub trait EndianScalar: Sized + PartialEq + Copy + Clone { pub trait EndianScalar: Sized + PartialEq + Copy + Clone {
fn to_little_endian(self) -> Self; type Scalar: private::TriviallyTransmutable;
fn from_little_endian(self) -> Self;
}
/// Macro for implementing a no-op endian conversion. This is used for types fn to_little_endian(self) -> Self::Scalar;
/// that are one byte wide.
macro_rules! impl_endian_scalar_noop { fn from_little_endian(v: Self::Scalar) -> Self;
($ty:ident) => {
impl EndianScalar for $ty {
#[inline]
fn to_little_endian(self) -> Self {
self
}
#[inline]
fn from_little_endian(self) -> Self {
self
}
}
};
} }
/// Macro for implementing an endian conversion using the stdlib `to_le` and /// Macro for implementing an endian conversion using the stdlib `to_le` and
/// `from_le` functions. This is used for integer types. It is not used for /// `from_le` functions. This is used for integer types. It is not used for
/// floats, because the `to_le` and `from_le` are not implemented for them in /// floats, because the `to_le` and `from_le` are not implemented for them in
/// the stdlib. /// the stdlib.
macro_rules! impl_endian_scalar_stdlib_le_conversion { macro_rules! impl_endian_scalar {
($ty:ident) => { ($ty:ident) => {
impl EndianScalar for $ty { impl EndianScalar for $ty {
type Scalar = Self;
#[inline] #[inline]
fn to_little_endian(self) -> Self { fn to_little_endian(self) -> Self::Scalar {
Self::to_le(self) Self::to_le(self)
} }
#[inline] #[inline]
fn from_little_endian(self) -> Self { fn from_little_endian(v: Self::Scalar) -> Self {
Self::from_le(self) Self::from_le(v)
} }
} }
}; };
} }
impl_endian_scalar_noop!(bool); impl_endian_scalar!(u8);
impl_endian_scalar_noop!(u8); impl_endian_scalar!(i8);
impl_endian_scalar_noop!(i8); impl_endian_scalar!(u16);
impl_endian_scalar!(u32);
impl_endian_scalar!(u64);
impl_endian_scalar!(i16);
impl_endian_scalar!(i32);
impl_endian_scalar!(i64);
impl_endian_scalar_stdlib_le_conversion!(u16); impl EndianScalar for bool {
impl_endian_scalar_stdlib_le_conversion!(u32); type Scalar = u8;
impl_endian_scalar_stdlib_le_conversion!(u64);
impl_endian_scalar_stdlib_le_conversion!(i16); fn to_little_endian(self) -> Self::Scalar {
impl_endian_scalar_stdlib_le_conversion!(i32); self as u8
impl_endian_scalar_stdlib_le_conversion!(i64); }
fn from_little_endian(v: Self::Scalar) -> Self {
v != 0
}
}
impl EndianScalar for f32 { impl EndianScalar for f32 {
type Scalar = u32;
/// Convert f32 from host endian-ness to little-endian. /// Convert f32 from host endian-ness to little-endian.
#[inline] #[inline]
fn to_little_endian(self) -> Self { fn to_little_endian(self) -> u32 {
#[cfg(target_endian = "little")] // Floats and Ints have the same endianness on all supported platforms.
{ // <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
self self.to_bits().to_le()
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(self)
}
} }
/// Convert f32 from little-endian to host endian-ness. /// Convert f32 from little-endian to host endian-ness.
#[inline] #[inline]
fn from_little_endian(self) -> Self { fn from_little_endian(v: u32) -> Self {
#[cfg(target_endian = "little")] // Floats and Ints have the same endianness on all supported platforms.
{ // <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
self f32::from_bits(u32::from_le(v))
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(self)
}
} }
} }
impl EndianScalar for f64 { impl EndianScalar for f64 {
type Scalar = u64;
/// Convert f64 from host endian-ness to little-endian. /// Convert f64 from host endian-ness to little-endian.
#[inline] #[inline]
fn to_little_endian(self) -> Self { fn to_little_endian(self) -> u64 {
#[cfg(target_endian = "little")] // Floats and Ints have the same endianness on all supported platforms.
{ // <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
self self.to_bits().to_le()
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(self)
}
} }
/// Convert f64 from little-endian to host endian-ness. /// Convert f64 from little-endian to host endian-ness.
#[inline] #[inline]
fn from_little_endian(self) -> Self { fn from_little_endian(v: u64) -> Self {
#[cfg(target_endian = "little")] // Floats and Ints have the same endianness on all supported platforms.
{ // <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
self f64::from_bits(u64::from_le(v))
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(self)
}
} }
} }
/// Swaps the bytes of an f32.
#[allow(dead_code)]
#[inline]
pub fn byte_swap_f32(x: f32) -> f32 {
f32::from_bits(x.to_bits().swap_bytes())
}
/// Swaps the bytes of an f64.
#[allow(dead_code)]
#[inline]
pub fn byte_swap_f64(x: f64) -> f64 {
f64::from_bits(x.to_bits().swap_bytes())
}
/// Place an EndianScalar into the provided mutable byte slice. Performs /// Place an EndianScalar into the provided mutable byte slice. Performs
/// endian conversion, if necessary. /// endian conversion, if necessary.
/// # Safety /// # Safety
/// Caller must ensure `s.len() > size_of::<T>()` /// Caller must ensure `s.len() >= size_of::<T>()`
/// and `x` does not overlap with `s`.
#[inline] #[inline]
pub unsafe fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) { pub unsafe fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
let size = size_of::<T::Scalar>();
debug_assert!(
s.len() >= size,
"insufficient capacity for emplace_scalar, needed {} got {}",
size,
s.len()
);
let x_le = x.to_little_endian(); let x_le = x.to_little_endian();
core::ptr::copy_nonoverlapping( core::ptr::copy_nonoverlapping(
&x_le as *const T as *const u8, &x_le as *const T::Scalar as *const u8,
s.as_mut_ptr() as *mut u8, s.as_mut_ptr() as *mut u8,
size_of::<T>(), size,
); );
} }
/// Read an EndianScalar from the provided byte slice at the specified location. /// Read an EndianScalar from the provided byte slice at the specified location.
/// Performs endian conversion, if necessary. /// Performs endian conversion, if necessary.
/// # Safety /// # Safety
/// Caller must ensure `s.len() > loc + size_of::<T>()`. /// Caller must ensure `s.len() >= loc + size_of::<T>()`.
#[inline] #[inline]
pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T { pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
read_scalar(&s[loc..]) read_scalar(&s[loc..])
@@ -177,8 +169,16 @@ pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
/// Caller must ensure `s.len() > size_of::<T>()`. /// Caller must ensure `s.len() > size_of::<T>()`.
#[inline] #[inline]
pub unsafe fn read_scalar<T: EndianScalar>(s: &[u8]) -> T { pub unsafe fn read_scalar<T: EndianScalar>(s: &[u8]) -> T {
let mut mem = core::mem::MaybeUninit::<T>::uninit(); let size = size_of::<T::Scalar>();
debug_assert!(
s.len() >= size,
"insufficient capacity for emplace_scalar, needed {} got {}",
size,
s.len()
);
let mut mem = core::mem::MaybeUninit::<T::Scalar>::uninit();
// Since [u8] has alignment 1, we copy it into T which may have higher alignment. // Since [u8] has alignment 1, we copy it into T which may have higher alignment.
core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size_of::<T>()); core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size);
mem.assume_init().from_little_endian() T::from_little_endian(mem.assume_init())
} }

View File

@@ -29,7 +29,11 @@ use core::marker::PhantomData;
/// continue traversing the FlatBuffer. /// continue traversing the FlatBuffer.
pub trait Follow<'buf> { pub trait Follow<'buf> {
type Inner; type Inner;
fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner; /// # Safety
///
/// `buf[loc..]` must contain a valid value of `Self` and anything it
/// transitively refers to by offset must also be valid
unsafe fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
} }
/// FollowStart wraps a Follow impl in a struct type. This can make certain /// FollowStart wraps a Follow impl in a struct type. This can make certain
@@ -39,17 +43,21 @@ pub struct FollowStart<T>(PhantomData<T>);
impl<'a, T: Follow<'a> + 'a> FollowStart<T> { impl<'a, T: Follow<'a> + 'a> FollowStart<T> {
#[inline] #[inline]
pub fn new() -> Self { pub fn new() -> Self {
Self { 0: PhantomData } Self(PhantomData)
} }
/// # Safety
///
/// `buf[loc..]` must contain a valid value of `T`
#[inline] #[inline]
pub fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner { pub unsafe fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner {
T::follow(buf, loc) T::follow(buf, loc)
} }
} }
impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> { impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline] #[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
T::follow(buf, loc) T::follow(buf, loc)
} }
} }

View File

@@ -45,6 +45,8 @@ where
{ {
let mut v = Verifier::new(opts, data); let mut v = Verifier::new(opts, data);
<ForwardsUOffset<T>>::run_verifier(&mut v, 0)?; <ForwardsUOffset<T>>::run_verifier(&mut v, 0)?;
// Safety:
// Run verifier above
Ok(unsafe { root_unchecked::<T>(data) }) Ok(unsafe { root_unchecked::<T>(data) })
} }
@@ -75,6 +77,8 @@ where
{ {
let mut v = Verifier::new(opts, data); let mut v = Verifier::new(opts, data);
<SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?; <SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?;
// Safety:
// Run verifier above
Ok(unsafe { size_prefixed_root_unchecked::<T>(data) }) Ok(unsafe { size_prefixed_root_unchecked::<T>(data) })
} }

View File

@@ -28,9 +28,10 @@
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers> //! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.) //! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
#![cfg_attr(feature = "no_std", no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
#[cfg(feature = "no_std")] #[cfg(not(feature = "std"))]
extern crate alloc; extern crate alloc;
mod array; mod array;
@@ -48,14 +49,12 @@ mod vtable_writer;
pub use crate::array::{array_init, emplace_scalar_array, Array}; pub use crate::array::{array_init, emplace_scalar_array, Array};
pub use crate::builder::FlatBufferBuilder; pub use crate::builder::FlatBufferBuilder;
pub use crate::endian_scalar::{ pub use crate::endian_scalar::{emplace_scalar, read_scalar, read_scalar_at, EndianScalar};
byte_swap_f32, byte_swap_f64, emplace_scalar, read_scalar, read_scalar_at, EndianScalar,
};
pub use crate::follow::{Follow, FollowStart}; pub use crate::follow::{Follow, FollowStart};
pub use crate::primitives::*; pub use crate::primitives::*;
pub use crate::push::Push; pub use crate::push::Push;
pub use crate::table::{buffer_has_identifier, Table}; pub use crate::table::{buffer_has_identifier, Table};
pub use crate::vector::{follow_cast_ref, SafeSliceAccess, Vector, VectorIter}; pub use crate::vector::{follow_cast_ref, Vector, VectorIter};
pub use crate::verifier::{ pub use crate::verifier::{
ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier, ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier,
VerifierOptions, VerifierOptions,
@@ -64,6 +63,4 @@ pub use crate::vtable::field_index_to_field_offset;
pub use bitflags; pub use bitflags;
pub use get_root::*; pub use get_root::*;
// TODO(rw): Unify `create_vector` and `create_vector_direct` by using
// `Into<Vector<...>>`.
// TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++. // TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++.

View File

@@ -112,10 +112,7 @@ impl<'a, T: 'a> WIPOffset<T> {
/// Create a new WIPOffset. /// Create a new WIPOffset.
#[inline] #[inline]
pub fn new(o: UOffsetT) -> WIPOffset<T> { pub fn new(o: UOffsetT) -> WIPOffset<T> {
WIPOffset { WIPOffset(o, PhantomData)
0: o,
1: PhantomData,
}
} }
/// Return a wrapped value that brings its meaning as a union WIPOffset /// Return a wrapped value that brings its meaning as a union WIPOffset
@@ -135,11 +132,9 @@ impl<T> Push for WIPOffset<T> {
type Output = ForwardsUOffset<T>; type Output = ForwardsUOffset<T>;
#[inline(always)] #[inline(always)]
fn push(&self, dst: &mut [u8], rest: &[u8]) { unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
let n = (SIZE_UOFFSET + rest.len() - self.value() as usize) as UOffsetT; let n = (SIZE_UOFFSET + written_len - self.value() as usize) as UOffsetT;
unsafe { emplace_scalar::<UOffsetT>(dst, n);
emplace_scalar::<UOffsetT>(dst, n);
}
} }
} }
@@ -147,8 +142,8 @@ impl<T> Push for ForwardsUOffset<T> {
type Output = Self; type Output = Self;
#[inline(always)] #[inline(always)]
fn push(&self, dst: &mut [u8], rest: &[u8]) { unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
self.value().push(dst, rest); self.value().push(dst, written_len);
} }
} }
@@ -179,9 +174,9 @@ impl<T> ForwardsUOffset<T> {
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset<T> { impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let slice = &buf[loc..loc + SIZE_UOFFSET]; let slice = &buf[loc..loc + SIZE_UOFFSET];
let off = unsafe { read_scalar::<u32>(slice) as usize }; let off = read_scalar::<u32>(slice) as usize;
T::follow(buf, loc + off) T::follow(buf, loc + off)
} }
} }
@@ -200,9 +195,9 @@ impl<T> ForwardsVOffset<T> {
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset<T> { impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let slice = &buf[loc..loc + SIZE_VOFFSET]; let slice = &buf[loc..loc + SIZE_VOFFSET];
let off = unsafe { read_scalar::<VOffsetT>(slice) as usize }; let off = read_scalar::<VOffsetT>(slice) as usize;
T::follow(buf, loc + off) T::follow(buf, loc + off)
} }
} }
@@ -211,8 +206,8 @@ impl<T> Push for ForwardsVOffset<T> {
type Output = Self; type Output = Self;
#[inline] #[inline]
fn push(&self, dst: &mut [u8], rest: &[u8]) { unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
self.value().push(dst, rest); self.value().push(dst, written_len);
} }
} }
@@ -230,9 +225,9 @@ impl<T> BackwardsSOffset<T> {
impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset<T> { impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let slice = &buf[loc..loc + SIZE_SOFFSET]; let slice = &buf[loc..loc + SIZE_SOFFSET];
let off = unsafe { read_scalar::<SOffsetT>(slice) }; let off = read_scalar::<SOffsetT>(slice);
T::follow(buf, (loc as SOffsetT - off) as usize) T::follow(buf, (loc as SOffsetT - off) as usize)
} }
} }
@@ -241,8 +236,8 @@ impl<T> Push for BackwardsSOffset<T> {
type Output = Self; type Output = Self;
#[inline] #[inline]
fn push(&self, dst: &mut [u8], rest: &[u8]) { unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
self.value().push(dst, rest); self.value().push(dst, written_len);
} }
} }
@@ -252,7 +247,7 @@ pub struct SkipSizePrefix<T>(PhantomData<T>);
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix<T> { impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
T::follow(buf, loc + SIZE_SIZEPREFIX) T::follow(buf, loc + SIZE_SIZEPREFIX)
} }
} }
@@ -263,7 +258,7 @@ pub struct SkipRootOffset<T>(PhantomData<T>);
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset<T> { impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
T::follow(buf, loc + SIZE_UOFFSET) T::follow(buf, loc + SIZE_UOFFSET)
} }
} }
@@ -274,7 +269,7 @@ pub struct FileIdentifier;
impl<'a> Follow<'a> for FileIdentifier { impl<'a> Follow<'a> for FileIdentifier {
type Inner = &'a [u8]; type Inner = &'a [u8];
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
&buf[loc..loc + FILE_IDENTIFIER_LENGTH] &buf[loc..loc + FILE_IDENTIFIER_LENGTH]
} }
} }
@@ -286,7 +281,7 @@ pub struct SkipFileIdentifier<T>(PhantomData<T>);
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> { impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
type Inner = T::Inner; type Inner = T::Inner;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
T::follow(buf, loc + FILE_IDENTIFIER_LENGTH) T::follow(buf, loc + FILE_IDENTIFIER_LENGTH)
} }
} }
@@ -294,8 +289,8 @@ impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
impl<'a> Follow<'a> for bool { impl<'a> Follow<'a> for bool {
type Inner = bool; type Inner = bool;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { read_scalar_at::<u8>(buf, loc) != 0 } read_scalar_at::<u8>(buf, loc) != 0
} }
} }
@@ -309,8 +304,8 @@ macro_rules! impl_follow_for_endian_scalar {
impl<'a> Follow<'a> for $ty { impl<'a> Follow<'a> for $ty {
type Inner = $ty; type Inner = $ty;
#[inline(always)] #[inline(always)]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { read_scalar_at::<$ty>(buf, loc) } read_scalar_at::<$ty>(buf, loc)
} }
} }
}; };

View File

@@ -24,7 +24,11 @@ use crate::endian_scalar::emplace_scalar;
/// types. /// types.
pub trait Push: Sized { pub trait Push: Sized {
type Output; type Output;
fn push(&self, dst: &mut [u8], _rest: &[u8]);
/// # Safety
///
/// dst is aligned to [`Self::alignment`] and has length greater than or equal to [`Self::size`]
unsafe fn push(&self, dst: &mut [u8], written_len: usize);
#[inline] #[inline]
fn size() -> usize { fn size() -> usize {
size_of::<Self::Output>() size_of::<Self::Output>()
@@ -35,13 +39,29 @@ pub trait Push: Sized {
} }
} }
impl<'a, T: Push> Push for &'a T {
type Output = T::Output;
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
T::push(self, dst, written_len)
}
fn size() -> usize {
T::size()
}
fn alignment() -> PushAlignment {
T::alignment()
}
}
/// Ensure Push alignment calculations are typesafe (because this helps reduce /// Ensure Push alignment calculations are typesafe (because this helps reduce
/// implementation issues when using FlatBufferBuilder::align). /// implementation issues when using FlatBufferBuilder::align).
pub struct PushAlignment(usize); pub struct PushAlignment(usize);
impl PushAlignment { impl PushAlignment {
#[inline] #[inline]
pub fn new(x: usize) -> Self { pub fn new(x: usize) -> Self {
PushAlignment { 0: x } PushAlignment(x)
} }
#[inline] #[inline]
pub fn value(&self) -> usize { pub fn value(&self) -> usize {
@@ -60,10 +80,8 @@ macro_rules! impl_push_for_endian_scalar {
type Output = $ty; type Output = $ty;
#[inline] #[inline]
fn push(&self, dst: &mut [u8], _rest: &[u8]) { unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
unsafe { emplace_scalar::<$ty>(dst, *self);
emplace_scalar::<$ty>(dst, *self);
}
} }
} }
}; };

View File

@@ -18,23 +18,46 @@ use crate::follow::Follow;
use crate::primitives::*; use crate::primitives::*;
use crate::vtable::VTable; use crate::vtable::VTable;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Table<'a> { pub struct Table<'a> {
pub buf: &'a [u8], buf: &'a [u8],
pub loc: usize, loc: usize,
} }
impl<'a> Table<'a> { impl<'a> Table<'a> {
#[inline] #[inline]
pub fn new(buf: &'a [u8], loc: usize) -> Self { pub fn buf(&self) -> &'a [u8] {
self.buf
}
#[inline]
pub fn loc(&self) -> usize {
self.loc
}
/// # Safety
///
/// `buf` must contain a `soffset_t` at `loc`, which points to a valid vtable
#[inline]
pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
Table { buf, loc } Table { buf, loc }
} }
#[inline] #[inline]
pub fn vtable(&self) -> VTable<'a> { pub fn vtable(&self) -> VTable<'a> {
<BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc) // Safety:
// Table::new is created with a valid buf and location
unsafe { <BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc) }
} }
/// Retrieves the value at the provided `slot_byte_loc` returning `default`
/// if no value present
///
/// # Safety
///
/// The value of the corresponding slot must have type T
#[inline] #[inline]
pub fn get<T: Follow<'a> + 'a>( pub unsafe fn get<T: Follow<'a> + 'a>(
&self, &self,
slot_byte_loc: VOffsetT, slot_byte_loc: VOffsetT,
default: Option<T::Inner>, default: Option<T::Inner>,
@@ -50,19 +73,26 @@ impl<'a> Table<'a> {
impl<'a> Follow<'a> for Table<'a> { impl<'a> Follow<'a> for Table<'a> {
type Inner = Table<'a>; type Inner = Table<'a>;
#[inline] #[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Table { buf, loc } Table { buf, loc }
} }
} }
/// Returns true if data contains a prefix of `ident`
#[inline] #[inline]
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool { pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool {
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH); assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
let got = if size_prefixed { let got = if size_prefixed {
<SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0) assert!(data.len() >= SIZE_SIZEPREFIX + SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
// Safety:
// Verified data has sufficient bytes
unsafe { <SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0) }
} else { } else {
<SkipRootOffset<FileIdentifier>>::follow(data, 0) assert!(data.len() >= SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
// Safety:
// Verified data has sufficient bytes
unsafe { <SkipRootOffset<FileIdentifier>>::follow(data, 0) }
}; };
ident.as_bytes() == got ident.as_bytes() == got

View File

@@ -17,13 +17,10 @@
use core::fmt::{Debug, Formatter, Result}; use core::fmt::{Debug, Formatter, Result};
use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator}; use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::size_of; use core::mem::{align_of, size_of};
use core::slice::from_raw_parts;
use core::str::from_utf8_unchecked; use core::str::from_utf8_unchecked;
use crate::endian_scalar::read_scalar_at; use crate::endian_scalar::read_scalar_at;
#[cfg(target_endian = "little")]
use crate::endian_scalar::EndianScalar;
use crate::follow::Follow; use crate::follow::Follow;
use crate::primitives::*; use crate::primitives::*;
@@ -55,6 +52,7 @@ where
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>` // and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
// can always be copied, no matter that `T` you have. // can always be copied, no matter that `T` you have.
impl<'a, T> Copy for Vector<'a, T> {} impl<'a, T> Copy for Vector<'a, T> {}
impl<'a, T> Clone for Vector<'a, T> { impl<'a, T> Clone for Vector<'a, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
@@ -62,32 +60,46 @@ impl<'a, T> Clone for Vector<'a, T> {
} }
impl<'a, T: 'a> Vector<'a, T> { impl<'a, T: 'a> Vector<'a, T> {
/// # Safety
///
/// `buf` contains a valid vector at `loc` consisting of
///
/// - UOffsetT element count
/// - Consecutive list of `T` elements
#[inline(always)] #[inline(always)]
pub fn new(buf: &'a [u8], loc: usize) -> Self { pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
Vector { Vector(buf, loc, PhantomData)
0: buf,
1: loc,
2: PhantomData,
}
} }
#[inline(always)] #[inline(always)]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
// Safety:
// Valid vector at time of construction starting with UOffsetT element count
unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize } unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
} }
#[inline(always)] #[inline(always)]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.len() == 0 self.len() == 0
} }
#[inline(always)]
pub fn bytes(&self) -> &'a [u8] {
let sz = size_of::<T>();
let len = self.len();
&self.0[self.1 + SIZE_UOFFSET..self.1 + SIZE_UOFFSET + sz * len]
}
} }
impl<'a, T: Follow<'a> + 'a> Vector<'a, T> { impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
#[inline(always)] #[inline(always)]
pub fn get(&self, idx: usize) -> T::Inner { pub fn get(&self, idx: usize) -> T::Inner {
assert!(idx < self.len() as usize); assert!(idx < self.len());
let sz = size_of::<T>(); let sz = size_of::<T>();
debug_assert!(sz > 0); debug_assert!(sz > 0);
T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) // Safety:
// Valid vector at time of construction, verified that idx < element count
unsafe { T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) }
} }
#[inline(always)] #[inline(always)]
@@ -96,84 +108,40 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
} }
} }
pub trait SafeSliceAccess {} /// # Safety
impl<'a, T: SafeSliceAccess + 'a> Vector<'a, T> { ///
pub fn safe_slice(self) -> &'a [T] { /// `buf` must contain a value of T at `loc` and have alignment of 1
let buf = self.0; pub unsafe fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
let loc = self.1; assert_eq!(align_of::<T>(), 1);
let sz = size_of::<T>();
debug_assert!(sz > 0);
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
let ptr = data_buf.as_ptr() as *const T;
let s: &'a [T] = unsafe { from_raw_parts(ptr, len) };
s
}
}
impl SafeSliceAccess for u8 {}
impl SafeSliceAccess for i8 {}
impl SafeSliceAccess for bool {}
// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity.
// Vectors of primitives just don't work on big endian machines!!!
#[cfg(target_endian = "little")]
mod le_safe_slice_impls {
impl super::SafeSliceAccess for u16 {}
impl super::SafeSliceAccess for u32 {}
impl super::SafeSliceAccess for u64 {}
impl super::SafeSliceAccess for i16 {}
impl super::SafeSliceAccess for i32 {}
impl super::SafeSliceAccess for i64 {}
impl super::SafeSliceAccess for f32 {}
impl super::SafeSliceAccess for f64 {}
}
#[cfg(target_endian = "little")]
pub use self::le_safe_slice_impls::*;
pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
let sz = size_of::<T>(); let sz = size_of::<T>();
let buf = &buf[loc..loc + sz]; let buf = &buf[loc..loc + sz];
let ptr = buf.as_ptr() as *const T; let ptr = buf.as_ptr() as *const T;
unsafe { &*ptr } // SAFETY
// buf contains a value at loc of type T and T has no alignment requirements
&*ptr
} }
impl<'a> Follow<'a> for &'a str { impl<'a> Follow<'a> for &'a str {
type Inner = &'a str; type Inner = &'a str;
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize; let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]; let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
unsafe { from_utf8_unchecked(slice) } from_utf8_unchecked(slice)
} }
} }
#[cfg(target_endian = "little")] impl<'a> Follow<'a> for &'a [u8] {
fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] { type Inner = &'a [u8];
let sz = size_of::<T>(); unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
debug_assert!(sz > 0); let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) as usize }; &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
let ptr = data_buf.as_ptr() as *const T;
let s: &[T] = unsafe { from_raw_parts(ptr, len) };
s
}
/// Implement direct slice access if the host is little-endian.
#[cfg(target_endian = "little")]
impl<'a, T: EndianScalar> Follow<'a> for &'a [T] {
type Inner = &'a [T];
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
follow_slice_helper::<T>(buf, loc)
} }
} }
/// Implement Follow for all possible Vectors that have Follow-able elements. /// Implement Follow for all possible Vectors that have Follow-able elements.
impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> { impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> {
type Inner = Vector<'a, T>; type Inner = Vector<'a, T>;
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Vector::new(buf, loc) Vector::new(buf, loc)
} }
} }
@@ -201,8 +169,14 @@ impl<'a, T: 'a> VectorIter<'a, T> {
} }
} }
/// Creates a new `VectorIter` from the provided slice
///
/// # Safety
///
/// buf must contain a contiguous sequence of `items_num` values of `T`
///
#[inline] #[inline]
pub fn from_slice(buf: &'a [u8], items_num: usize) -> Self { pub unsafe fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
VectorIter { VectorIter {
buf, buf,
loc: 0, loc: 0,
@@ -235,7 +209,10 @@ impl<'a, T: Follow<'a> + 'a> Iterator for VectorIter<'a, T> {
if self.remaining == 0 { if self.remaining == 0 {
None None
} else { } else {
let result = T::follow(self.buf, self.loc); // Safety:
// VectorIter can only be created from a contiguous sequence of `items_num`
// And remaining is initialized to `items_num`
let result = unsafe { T::follow(self.buf, self.loc) };
self.loc += sz; self.loc += sz;
self.remaining -= 1; self.remaining -= 1;
Some(result) Some(result)
@@ -272,7 +249,10 @@ impl<'a, T: Follow<'a> + 'a> DoubleEndedIterator for VectorIter<'a, T> {
None None
} else { } else {
self.remaining -= 1; self.remaining -= 1;
Some(T::follow(self.buf, self.loc + sz * self.remaining)) // Safety:
// VectorIter can only be created from a contiguous sequence of `items_num`
// And remaining is initialized to `items_num`
Some(unsafe { T::follow(self.buf, self.loc + sz * self.remaining) })
} }
} }
@@ -309,7 +289,7 @@ impl<'a, 'b, T: Follow<'a> + 'a> IntoIterator for &'b Vector<'a, T> {
} }
} }
#[cfg(feature="serialize")] #[cfg(feature = "serialize")]
impl<'a, T> serde::ser::Serialize for Vector<'a, T> impl<'a, T> serde::ser::Serialize for Vector<'a, T>
where where
T: 'a + Follow<'a>, T: 'a + Follow<'a>,

View File

@@ -1,14 +1,14 @@
#[cfg(feature = "no_std")] use crate::follow::Follow;
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ops::Range; use core::ops::Range;
use core::option::Option; use core::option::Option;
use crate::follow::Follow;
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
#[cfg(feature="no_std")] #[cfg(all(nightly, not(feature = "std")))]
use thiserror_core2::Error; use core::error::Error;
#[cfg(not(feature="no_std"))] #[cfg(feature = "std")]
use thiserror::Error; use std::error::Error;
/// Traces the location of data errors. Not populated for Dos detecting errors. /// Traces the location of data errors. Not populated for Dos detecting errors.
/// Useful for MissingRequiredField and Utf8Error in particular, though /// Useful for MissingRequiredField and Utf8Error in particular, though
@@ -28,8 +28,10 @@ pub enum ErrorTraceDetail {
position: usize, position: usize,
}, },
} }
#[derive(PartialEq, Eq, Default, Debug, Clone)] #[derive(PartialEq, Eq, Default, Debug, Clone)]
pub struct ErrorTrace(Vec<ErrorTraceDetail>); pub struct ErrorTrace(Vec<ErrorTraceDetail>);
impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace { impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
#[inline] #[inline]
fn as_ref(&self) -> &[ErrorTraceDetail] { fn as_ref(&self) -> &[ErrorTraceDetail] {
@@ -39,64 +41,138 @@ impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing /// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
/// information is given for DoS detecting errors since it will probably be a lot. /// information is given for DoS detecting errors since it will probably be a lot.
#[derive(Clone, Error, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum InvalidFlatbuffer { pub enum InvalidFlatbuffer {
#[error("Missing required field `{required}`.\n{error_trace}")]
MissingRequiredField { MissingRequiredField {
required: &'static str, required: &'static str,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error(
"Union exactly one of union discriminant (`{field_type}`) and value \
(`{field}`) are present.\n{error_trace}"
)]
InconsistentUnion { InconsistentUnion {
field: &'static str, field: &'static str,
field_type: &'static str, field_type: &'static str,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
Utf8Error { Utf8Error {
#[source]
error: core::str::Utf8Error, error: core::str::Utf8Error,
range: Range<usize>, range: Range<usize>,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
range.start, range.end)]
MissingNullTerminator { MissingNullTerminator {
range: Range<usize>, range: Range<usize>,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
Unaligned { Unaligned {
position: usize, position: usize,
unaligned_type: &'static str, unaligned_type: &'static str,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
RangeOutOfBounds { RangeOutOfBounds {
range: Range<usize>, range: Range<usize>,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
#[error(
"Signed offset at position {position} has value {soffset} which points out of bounds.\
\n{error_trace}"
)]
SignedOffsetOutOfBounds { SignedOffsetOutOfBounds {
soffset: SOffsetT, soffset: SOffsetT,
position: usize, position: usize,
error_trace: ErrorTrace, error_trace: ErrorTrace,
}, },
// Dos detecting errors. These do not get error traces since it will probably be very large. // Dos detecting errors. These do not get error traces since it will probably be very large.
#[error("Too many tables.")]
TooManyTables, TooManyTables,
#[error("Apparent size too large.")]
ApparentSizeTooLarge, ApparentSizeTooLarge,
#[error("Nested table depth limit reached.")]
DepthLimitReached, DepthLimitReached,
} }
#[cfg(any(nightly, feature = "std"))]
impl Error for InvalidFlatbuffer {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let InvalidFlatbuffer::Utf8Error { error: source, .. } = self {
Some(source)
} else {
None
}
}
}
impl core::fmt::Display for InvalidFlatbuffer {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
InvalidFlatbuffer::MissingRequiredField {
required,
error_trace,
} => {
writeln!(f, "Missing required field `{}`.\n{}", required, error_trace)?;
}
InvalidFlatbuffer::InconsistentUnion {
field,
field_type,
error_trace,
} => {
writeln!(
f,
"Exactly one of union discriminant (`{}`) and value (`{}`) are present.\n{}",
field_type, field, error_trace
)?;
}
InvalidFlatbuffer::Utf8Error {
error,
range,
error_trace,
} => {
writeln!(
f,
"Utf8 error for string in {:?}: {}\n{}",
range, error, error_trace
)?;
}
InvalidFlatbuffer::MissingNullTerminator { range, error_trace } => {
writeln!(
f,
"String in range [{}, {}) is missing its null terminator.\n{}",
range.start, range.end, error_trace
)?;
}
InvalidFlatbuffer::Unaligned {
position,
unaligned_type,
error_trace,
} => {
writeln!(
f,
"Type `{}` at position {} is unaligned.\n{}",
unaligned_type, position, error_trace
)?;
}
InvalidFlatbuffer::RangeOutOfBounds { range, error_trace } => {
writeln!(
f,
"Range [{}, {}) is out of bounds.\n{}",
range.start, range.end, error_trace
)?;
}
InvalidFlatbuffer::SignedOffsetOutOfBounds {
soffset,
position,
error_trace,
} => {
writeln!(
f,
"Signed offset at position {} has value {} which points out of bounds.\n{}",
position, soffset, error_trace
)?;
}
InvalidFlatbuffer::TooManyTables {} => {
writeln!(f, "Too many tables.")?;
}
InvalidFlatbuffer::ApparentSizeTooLarge {} => {
writeln!(f, "Apparent size too large.")?;
}
InvalidFlatbuffer::DepthLimitReached {} => {
writeln!(f, "Nested table depth limit reached.")?;
}
}
Ok(())
}
}
impl core::fmt::Display for ErrorTrace { impl core::fmt::Display for ErrorTrace {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use ErrorTraceDetail::*; use ErrorTraceDetail::*;
@@ -184,6 +260,7 @@ fn trace_field<T>(res: Result<T>, field_name: &'static str, position: usize) ->
}, },
) )
} }
/// Adds a TableField trace detail if `res` is a data error. /// Adds a TableField trace detail if `res` is a data error.
fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> { fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> {
append_trace(res, ErrorTraceDetail::VectorElement { index, position }) append_trace(res, ErrorTraceDetail::VectorElement { index, position })
@@ -205,6 +282,7 @@ pub struct VerifierOptions {
// options to error un-recognized enums and unions? possible footgun. // options to error un-recognized enums and unions? possible footgun.
// Ignore nested flatbuffers, etc? // Ignore nested flatbuffers, etc?
} }
impl Default for VerifierOptions { impl Default for VerifierOptions {
fn default() -> Self { fn default() -> Self {
Self { Self {
@@ -226,6 +304,7 @@ pub struct Verifier<'opts, 'buf> {
num_tables: usize, num_tables: usize,
apparent_size: usize, apparent_size: usize,
} }
impl<'opts, 'buf> Verifier<'opts, 'buf> { impl<'opts, 'buf> Verifier<'opts, 'buf> {
pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self { pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self {
Self { Self {
@@ -247,9 +326,12 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
/// memory since `buffer: &[u8]` has alignment 1. /// memory since `buffer: &[u8]` has alignment 1.
/// ///
/// ### WARNING /// ### WARNING
///
/// This does not work for flatbuffers-structs as they have alignment 1 according to /// This does not work for flatbuffers-structs as they have alignment 1 according to
/// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t. /// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t.
/// `buffer[0]`. TODO(caspern). /// `buffer[0]`. TODO(caspern).
///
/// Note this does not impact soundness as this crate does not assume alignment of structs
#[inline] #[inline]
fn is_aligned<T>(&self, pos: usize) -> Result<()> { fn is_aligned<T>(&self, pos: usize) -> Result<()> {
if pos % core::mem::align_of::<T>() == 0 { if pos % core::mem::align_of::<T>() == 0 {
@@ -307,9 +389,9 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
// signed offsets are subtracted. // signed offsets are subtracted.
let derefed = if offset > 0 { let derefed = if offset > 0 {
pos.checked_sub(offset.abs() as usize) pos.checked_sub(offset.unsigned_abs() as usize)
} else { } else {
pos.checked_add(offset.abs() as usize) pos.checked_add(offset.unsigned_abs() as usize)
}; };
if let Some(x) = derefed { if let Some(x) = derefed {
if x < self.buffer.len() { if x < self.buffer.len() {
@@ -372,6 +454,7 @@ pub struct TableVerifier<'ver, 'opts, 'buf> {
// Verifier struct which holds the surrounding state and options. // Verifier struct which holds the surrounding state and options.
verifier: &'ver mut Verifier<'opts, 'buf>, verifier: &'ver mut Verifier<'opts, 'buf>,
} }
impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> { impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> { fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> {
let field = field as usize; let field = field as usize;
@@ -439,7 +522,9 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
} }
(Some(k), Some(v)) => { (Some(k), Some(v)) => {
trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?; trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?;
let discriminant = Key::follow(self.verifier.buffer, k); // Safety:
// Run verifier on `k` above
let discriminant = unsafe { Key::follow(self.verifier.buffer, k) };
trace_field( trace_field(
verify_union(discriminant, self.verifier, v), verify_union(discriminant, self.verifier, v),
val_field_name, val_field_name,
@@ -486,16 +571,27 @@ fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<core::ops::Ran
} }
pub trait SimpleToVerifyInSlice {} pub trait SimpleToVerifyInSlice {}
impl SimpleToVerifyInSlice for bool {} impl SimpleToVerifyInSlice for bool {}
impl SimpleToVerifyInSlice for i8 {} impl SimpleToVerifyInSlice for i8 {}
impl SimpleToVerifyInSlice for u8 {} impl SimpleToVerifyInSlice for u8 {}
impl SimpleToVerifyInSlice for i16 {} impl SimpleToVerifyInSlice for i16 {}
impl SimpleToVerifyInSlice for u16 {} impl SimpleToVerifyInSlice for u16 {}
impl SimpleToVerifyInSlice for i32 {} impl SimpleToVerifyInSlice for i32 {}
impl SimpleToVerifyInSlice for u32 {} impl SimpleToVerifyInSlice for u32 {}
impl SimpleToVerifyInSlice for f32 {} impl SimpleToVerifyInSlice for f32 {}
impl SimpleToVerifyInSlice for i64 {} impl SimpleToVerifyInSlice for i64 {}
impl SimpleToVerifyInSlice for u64 {} impl SimpleToVerifyInSlice for u64 {}
impl SimpleToVerifyInSlice for f64 {} impl SimpleToVerifyInSlice for f64 {}
impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> { impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> {

View File

@@ -33,24 +33,42 @@ impl<'a> PartialEq for VTable<'a> {
} }
impl<'a> VTable<'a> { impl<'a> VTable<'a> {
pub fn init(buf: &'a [u8], loc: usize) -> Self { /// SAFETY
/// `buf` must contain a valid vtable at `loc`
///
/// This consists of a number of `VOffsetT`
/// - size of vtable in bytes including size element
/// - size of object in bytes including the vtable offset
/// - n fields where n is the number of fields in the table's schema when the code was compiled
pub unsafe fn init(buf: &'a [u8], loc: usize) -> Self {
VTable { buf, loc } VTable { buf, loc }
} }
pub fn num_fields(&self) -> usize { pub fn num_fields(&self) -> usize {
(self.num_bytes() / SIZE_VOFFSET) - 2 (self.num_bytes() / SIZE_VOFFSET) - 2
} }
pub fn num_bytes(&self) -> usize { pub fn num_bytes(&self) -> usize {
// Safety:
// Valid VTable at time of construction
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc) as usize } unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc) as usize }
} }
pub fn object_inline_num_bytes(&self) -> usize { pub fn object_inline_num_bytes(&self) -> usize {
// Safety:
// Valid VTable at time of construction
let n = unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + SIZE_VOFFSET) }; let n = unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + SIZE_VOFFSET) };
n as usize n as usize
} }
pub fn get_field(&self, idx: usize) -> VOffsetT { pub fn get_field(&self, idx: usize) -> VOffsetT {
// TODO(rw): distinguish between None and 0? // TODO(rw): distinguish between None and 0?
if idx > self.num_fields() { if idx > self.num_fields() {
return 0; return 0;
} }
// Safety:
// Valid VTable at time of construction
unsafe { unsafe {
read_scalar_at::<VOffsetT>( read_scalar_at::<VOffsetT>(
self.buf, self.buf,
@@ -58,13 +76,17 @@ impl<'a> VTable<'a> {
) )
} }
} }
pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT { pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT {
// TODO(rw): distinguish between None and 0? // TODO(rw): distinguish between None and 0?
if byte_loc as usize >= self.num_bytes() { if byte_loc as usize + 2 > self.num_bytes() {
return 0; return 0;
} }
// Safety:
// byte_loc is within bounds of vtable, which was valid at time of construction
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + byte_loc as usize) } unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + byte_loc as usize) }
} }
pub fn as_bytes(&self) -> &[u8] { pub fn as_bytes(&self) -> &[u8] {
let len = self.num_bytes(); let len = self.num_bytes();
&self.buf[self.loc..self.loc + len] &self.buf[self.loc..self.loc + len]
@@ -87,7 +109,7 @@ pub fn field_offset_to_field_index(field_o: VOffsetT) -> VOffsetT {
impl<'a> Follow<'a> for VTable<'a> { impl<'a> Follow<'a> for VTable<'a> {
type Inner = VTable<'a>; type Inner = VTable<'a>;
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
VTable::init(buf, loc) VTable::init(buf, loc)
} }
} }

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