Compare commits

...

57 Commits

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


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

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

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

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

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

* Fix indentation

---------

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

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

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

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

* [C#] Fix verifying unions

---------

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

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

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

---------

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

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

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

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

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

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

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

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

* chore: clarify comment regarding offset

A full FlatBuffer structure would be:

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

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

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

---------

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

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

```
FAILURE: Build failed with an exception.

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

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

Update tests

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

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

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

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

* Format

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

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

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

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

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

* [Python] Remove unused variable

* [Python] Fix __eq__ for numpy arrays

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

* Fix Rust code generation for Rust edition 2024

The errors look like:

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

* Update goldens

Ran `goldens/generate_goldens.py`

* Regenerate code files

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

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

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

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

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

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

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

#### Example of a Generated `__init__`

**Before:**

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

**After:**

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

#### Example of User Code

**Before:**

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

**After:**

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

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

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

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

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

Otherwise mypy will correctly flag code like this

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

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

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

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

* Migrates to vapor that uses swiftly actions

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

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

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

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

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

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

Restoring the previous default `_fb` suffix.

* [Python] Use namespace in path

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

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

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

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

* Reading a flexbuffer

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

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

* Fixes bazel breaking due to new project structure

Address warnings within the library

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

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

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

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

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

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

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

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

Replaces assumingMemoryBinding with bindMemory which is safer

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

Updates docs

Suppress compilation warnings by replacing var with let

Using overflow operators within swift to improve performance

Adds tests for GRPC message creation from a retained _InternalByteBuffer
2025-03-18 07:48:39 +01:00
1016 changed files with 55118 additions and 39680 deletions

View File

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

View File

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

View File

@@ -129,7 +129,7 @@ jobs:
build-cpp-std:
name: Build Windows C++
runs-on: windows-2019
runs-on: windows-2022
strategy:
matrix:
std: [11, 14, 17, 20, 23]
@@ -140,7 +140,7 @@ jobs:
uses: microsoft/setup-msbuild@v1.1
- name: cmake
run: >
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release
cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
-DFLATBUFFERS_STRICT_MODE=ON
-DFLATBUFFERS_CPP_STD=${{ matrix.std }}
-DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}}
@@ -157,14 +157,14 @@ jobs:
contents: write
outputs:
digests: ${{ steps.hash.outputs.hashes }}
name: Build Windows 2019
runs-on: windows-2019
name: Build Windows 2022
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
- name: cmake
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: test
@@ -310,14 +310,17 @@ jobs:
build-android:
name: Build Android (on Linux)
if: false #disabled due to continual failure
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- name: set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: set up flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
@@ -344,13 +347,13 @@ jobs:
build-generator-windows:
name: Check Generated Code on Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
- name: cmake
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: Generate
@@ -398,11 +401,13 @@ jobs:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
- name: Set up Xcode version
run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
- uses: gradle/wrapper-validation-action@v1.0.5
- uses: actions/setup-java@v3
- name: set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -414,15 +419,18 @@ jobs:
build-kotlin-linux:
name: Build Kotlin Linux
if: false #disabled due to continual failure
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/setup-java@v3
- name: set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
- uses: gradle/wrapper-validation-action@v1.0.5
distribution: temurin
java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build flatc
run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -492,27 +500,37 @@ jobs:
sh phpUnionVectorTest.sh
build-swift:
name: Build Swift
name: Test Swift
strategy:
matrix:
swift: ["5.9", "5.10", "6.0"]
swift: ["5.9", "5.10", "6.1"]
# Only 22.04 has swift at the moment https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md?plain=1#L30
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: swift-actions/setup-swift@v2
- uses: vapor/swiftly-action@v0.2
with:
swift-version: ${{ matrix.swift }}
toolchain: ${{ matrix.swift }}
- name: Get swift version
run: swift --version
- name: test
working-directory: tests/swift/tests
run: |
swift build --build-tests
swift test
build-swift-windows:
name: Test swift windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: SwiftyLab/setup-swift@latest
with:
swift-version: '6.1'
- run: swift build
- run: swift test
build-swift-wasm:
name: Build Swift Wasm
name: Test Swift Wasm
runs-on: ubuntu-24.04
container:
image: ghcr.io/swiftwasm/carton:0.20.1
@@ -534,14 +552,15 @@ jobs:
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm
run: npm install -g pnpm esbuild
- name: deps
run: yarn
run: pnpm i
- name: compile
run: yarn compile
run: pnpm compile
- name: test
working-directory: tests/ts
run: |
yarn global add esbuild
python3 TypeScriptTest.py
build-dart:

View File

@@ -4,6 +4,13 @@ All major or breaking changes will be documented in this file, as well as any
new features that should be highlighted. Minor fixes or improvements are not
necessarily listed.
## [25.9.23] (September 23 2025)(https://github.com/google/flatbuffers/releases/tag/v25.9.23)
* flatc: `--grpc-callback-api` flag generates C++ gRPC Callback API server `CallbackService` skeletons AND client native callback/async stubs (unary + all streaming reactor forms) (opt-in, non-breaking, issue #8596).
* Swift - Adds new API to reduce memory copying within swift (#8484)
* Rust - Support Rust edition 2024 (#8638)
# [:C++] - Use the Google Style for clang-format without exceptions (#8706)
## [25.2.10] (February 10 2025)(https://github.com/google/flatbuffers/releases/tag/v25.2.10)
* Removed the old documentation pages. The new one is live at https://flatbuffers.dev

View File

@@ -1,6 +1,6 @@
set(VERSION_MAJOR 25)
set(VERSION_MINOR 2)
set(VERSION_PATCH 10)
set(VERSION_MINOR 9)
set(VERSION_PATCH 23)
set(VERSION_COMMIT 0)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")

View File

@@ -112,6 +112,7 @@ endif()
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
if(NOT WIN32)
include(CheckSymbolExists)
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
if(NOT HAVE_REALPATH)
add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION)
@@ -278,6 +279,8 @@ set(FlatBuffers_GRPCTest_SRCS
tests/test_builder.cpp
grpc/tests/grpctest.cpp
grpc/tests/message_builder_test.cpp
grpc/tests/grpctest_callback_compile.cpp
grpc/tests/grpctest_callback_client_compile.cpp
)
# TODO(dbaileychess): Figure out how this would now work. I posted a question on

View File

@@ -40,3 +40,26 @@ Some tips for good pull requests:
# The small print
Contributions made by corporations are covered by a different agreement than
the one above, the Software Grant and Corporate Contributor License Agreement.
# Code
TL/DR
See [how to build flatc](https://flatbuffers.dev/building/).
When making changes, build `flatc` and then re-generate the goldens files to see the effect of your changes:
```
$ cp build/flatc .
$ goldens/generate_goldens.py
```
Re-generate other code files to see the effects of the changes:
```
$ scripts/generate_code.py
```
Run tests with [TestAll.sh](tests/TestAll.sh) in [tests](tests), or directly any of the sub-scripts run by it.
[Format the code](Formatters.md) before submitting a PR.

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'FlatBuffers'
s.version = '25.2.10'
s.version = '25.9.23'
s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
s.description = "FlatBuffers is a cross platform serialization library architected for

View File

@@ -1,6 +1,6 @@
module(
name = "flatbuffers",
version = "25.2.10",
version = "25.9.23",
compatibility_level = 1,
repo_name = "com_github_google_flatbuffers",
)
@@ -15,11 +15,11 @@ bazel_dep(
)
bazel_dep(
name = "aspect_rules_js",
version = "2.1.3",
version = "2.3.8",
)
bazel_dep(
name = "aspect_rules_ts",
version = "3.4.0",
version = "3.6.0",
)
bazel_dep(
name = "grpc",

View File

@@ -20,17 +20,61 @@ import PackageDescription
let package = Package(
name: "FlatBuffers",
platforms: [
.iOS(.v11),
.iOS(.v12),
.macOS(.v10_14),
],
products: [
.library(
name: "FlatBuffers",
targets: ["FlatBuffers"]),
.library(
name: "FlexBuffers",
targets: ["FlexBuffers"]),
],
dependencies: .dependencies,
targets: [
.target(
name: "FlatBuffers",
dependencies: [],
path: "swift/Sources"),
dependencies: ["Common"],
path: "swift/Sources/FlatBuffers"),
.target(
name: "FlexBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlexBuffers"),
.target(
name: "Common",
path: "swift/Sources/Common"),
.testTarget(
name: "FlatbuffersTests",
dependencies: .dependencies,
path: "tests/swift/Tests/Flatbuffers"),
.testTarget(
name: "FlexbuffersTests",
dependencies: ["FlexBuffers"],
path: "tests/swift/Tests/Flexbuffers"),
])
extension Array where Element == Package.Dependency {
static var dependencies: [Package.Dependency] {
#if os(Windows)
[]
#else
// Test only Dependency
[.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.4.1")]
#endif
}
}
extension Array where Element == PackageDescription.Target.Dependency {
static var dependencies: [PackageDescription.Target.Dependency] {
#if os(Windows)
["FlatBuffers"]
#else
// Test only Dependency
[
.product(name: "GRPC", package: "grpc-swift"),
"FlatBuffers",
]
#endif
}
}

View File

@@ -1,4 +1,4 @@
![logo](http://google.github.io/flatbuffers/fpl_logo_small.png) FlatBuffers
![logo](https://flatbuffers.dev/assets/flatbuffers_logo.svg) FlatBuffers
===========
![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master)

View File

@@ -1,6 +1,5 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
#define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
@@ -33,17 +32,12 @@ struct Animal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
const ::flatbuffers::String* sound() const {
return GetPointer<const ::flatbuffers::String*>(VT_SOUND);
}
uint16_t weight() const {
return GetField<uint16_t>(VT_WEIGHT, 0);
}
uint16_t weight() const { return GetField<uint16_t>(VT_WEIGHT, 0); }
bool Verify(::flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_SOUND) &&
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) && VerifyOffset(verifier, VT_SOUND) &&
verifier.VerifyString(sound()) &&
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) &&
verifier.EndTable();
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) && verifier.EndTable();
}
};
@@ -60,8 +54,7 @@ struct AnimalBuilder {
void add_weight(uint16_t weight) {
fbb_.AddElement<uint16_t>(Animal::VT_WEIGHT, weight, 0);
}
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
::flatbuffers::Offset<Animal> Finish() {
@@ -84,17 +77,11 @@ inline ::flatbuffers::Offset<Animal> CreateAnimal(
}
inline ::flatbuffers::Offset<Animal> CreateAnimalDirect(
::flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
const char *sound = nullptr,
uint16_t weight = 0) {
::flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr,
const char* sound = nullptr, uint16_t weight = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto sound__ = sound ? _fbb.CreateString(sound) : 0;
return com::fbs::app::CreateAnimal(
_fbb,
name__,
sound__,
weight);
return com::fbs::app::CreateAnimal(_fbb, name__, sound__, weight);
}
inline const com::fbs::app::Animal* GetAnimal(const void* buf) {
@@ -105,13 +92,11 @@ inline const com::fbs::app::Animal *GetSizePrefixedAnimal(const void *buf) {
return ::flatbuffers::GetSizePrefixedRoot<com::fbs::app::Animal>(buf);
}
inline bool VerifyAnimalBuffer(
::flatbuffers::Verifier &verifier) {
inline bool VerifyAnimalBuffer(::flatbuffers::Verifier& verifier) {
return verifier.VerifyBuffer<com::fbs::app::Animal>(nullptr);
}
inline bool VerifySizePrefixedAnimalBuffer(
::flatbuffers::Verifier &verifier) {
inline bool VerifySizePrefixedAnimalBuffer(::flatbuffers::Verifier& verifier) {
return verifier.VerifySizePrefixedBuffer<com::fbs::app::Animal>(nullptr);
}

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
@@ -34,21 +33,12 @@ enum Enum : int16_t {
};
inline const Enum (&EnumValuesEnum())[3] {
static const Enum values[] = {
Enum_Apples,
Enum_Pears,
Enum_Bananas
};
static const Enum values[] = {Enum_Apples, Enum_Pears, Enum_Bananas};
return values;
}
inline const char* const* EnumNamesEnum() {
static const char * const names[4] = {
"Apples",
"Pears",
"Bananas",
nullptr
};
static const char* const names[4] = {"Apples", "Pears", "Bananas", nullptr};
return names;
}
@@ -67,12 +57,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
uint32_t length_;
public:
Foo()
: id_(0),
count_(0),
prefix_(0),
padding0__(0),
length_(0) {
Foo() : id_(0), count_(0), prefix_(0), padding0__(0), length_(0) {
(void)padding0__;
}
Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length)
@@ -83,18 +68,10 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
length_(flatbuffers::EndianScalar(_length)) {
(void)padding0__;
}
uint64_t id() const {
return flatbuffers::EndianScalar(id_);
}
int16_t count() const {
return flatbuffers::EndianScalar(count_);
}
int8_t prefix() const {
return flatbuffers::EndianScalar(prefix_);
}
uint32_t length() const {
return flatbuffers::EndianScalar(length_);
}
uint64_t id() const { return flatbuffers::EndianScalar(id_); }
int16_t count() const { return flatbuffers::EndianScalar(count_); }
int8_t prefix() const { return flatbuffers::EndianScalar(prefix_); }
uint32_t length() const { return flatbuffers::EndianScalar(length_); }
};
FLATBUFFERS_STRUCT_END(Foo, 16);
@@ -104,20 +81,17 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
int32_t time_;
float ratio_;
uint16_t size_;
int16_t padding0__; int32_t padding1__;
int16_t padding0__;
int32_t padding1__;
public:
Bar()
: parent_(),
time_(0),
ratio_(0),
size_(0),
padding0__(0),
padding1__(0) {
: parent_(), time_(0), ratio_(0), size_(0), padding0__(0), padding1__(0) {
(void)padding0__;
(void)padding1__;
}
Bar(const benchmarks_flatbuffers::Foo &_parent, int32_t _time, float _ratio, uint16_t _size)
Bar(const benchmarks_flatbuffers::Foo& _parent, int32_t _time, float _ratio,
uint16_t _size)
: parent_(_parent),
time_(flatbuffers::EndianScalar(_time)),
ratio_(flatbuffers::EndianScalar(_ratio)),
@@ -127,18 +101,10 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
(void)padding0__;
(void)padding1__;
}
const benchmarks_flatbuffers::Foo &parent() const {
return parent_;
}
int32_t time() const {
return flatbuffers::EndianScalar(time_);
}
float ratio() const {
return flatbuffers::EndianScalar(ratio_);
}
uint16_t size() const {
return flatbuffers::EndianScalar(size_);
}
const benchmarks_flatbuffers::Foo& parent() const { return parent_; }
int32_t time() const { return flatbuffers::EndianScalar(time_); }
float ratio() const { return flatbuffers::EndianScalar(ratio_); }
uint16_t size() const { return flatbuffers::EndianScalar(size_); }
};
FLATBUFFERS_STRUCT_END(Bar, 32);
@@ -156,20 +122,14 @@ struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(VT_NAME);
}
double rating() const {
return GetField<double>(VT_RATING, 0.0);
}
uint8_t postfix() const {
return GetField<uint8_t>(VT_POSTFIX, 0);
}
double rating() const { return GetField<double>(VT_RATING, 0.0); }
uint8_t postfix() const { return GetField<uint8_t>(VT_POSTFIX, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<benchmarks_flatbuffers::Bar>(verifier, VT_SIBLING, 8) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_NAME) && verifier.VerifyString(name()) &&
VerifyField<double>(verifier, VT_RATING, 8) &&
VerifyField<uint8_t>(verifier, VT_POSTFIX, 1) &&
verifier.EndTable();
VerifyField<uint8_t>(verifier, VT_POSTFIX, 1) && verifier.EndTable();
}
};
@@ -189,8 +149,7 @@ struct FooBarBuilder {
void add_postfix(uint8_t postfix) {
fbb_.AddElement<uint8_t>(FooBar::VT_POSTFIX, postfix, 0);
}
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<FooBar> Finish() {
@@ -203,8 +162,7 @@ struct FooBarBuilder {
inline flatbuffers::Offset<FooBar> CreateFooBar(
flatbuffers::FlatBufferBuilder& _fbb,
const benchmarks_flatbuffers::Bar* sibling = nullptr,
flatbuffers::Offset<flatbuffers::String> name = 0,
double rating = 0.0,
flatbuffers::Offset<flatbuffers::String> name = 0, double rating = 0.0,
uint8_t postfix = 0) {
FooBarBuilder builder_(_fbb);
builder_.add_rating(rating);
@@ -217,15 +175,9 @@ inline flatbuffers::Offset<FooBar> CreateFooBar(
inline flatbuffers::Offset<FooBar> CreateFooBarDirect(
flatbuffers::FlatBufferBuilder& _fbb,
const benchmarks_flatbuffers::Bar* sibling = nullptr,
const char *name = nullptr,
double rating = 0.0,
uint8_t postfix = 0) {
const char* name = nullptr, double rating = 0.0, uint8_t postfix = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0;
return benchmarks_flatbuffers::CreateFooBar(
_fbb,
sibling,
name__,
rating,
return benchmarks_flatbuffers::CreateFooBar(_fbb, sibling, name__, rating,
postfix);
}
@@ -237,28 +189,28 @@ struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FRUIT = 8,
VT_LOCATION = 10
};
const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *>(VT_LIST);
}
bool initialized() const {
return GetField<uint8_t>(VT_INITIALIZED, 0) != 0;
const flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*
list() const {
return GetPointer<const flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*>(VT_LIST);
}
bool initialized() const { return GetField<uint8_t>(VT_INITIALIZED, 0) != 0; }
benchmarks_flatbuffers::Enum fruit() const {
return static_cast<benchmarks_flatbuffers::Enum>(GetField<int16_t>(VT_FRUIT, 0));
return static_cast<benchmarks_flatbuffers::Enum>(
GetField<int16_t>(VT_FRUIT, 0));
}
const flatbuffers::String* location() const {
return GetPointer<const flatbuffers::String*>(VT_LOCATION);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_LIST) &&
return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_LIST) &&
verifier.VerifyVector(list()) &&
verifier.VerifyVectorOfTables(list()) &&
VerifyField<uint8_t>(verifier, VT_INITIALIZED, 1) &&
VerifyField<int16_t>(verifier, VT_FRUIT, 2) &&
VerifyOffset(verifier, VT_LOCATION) &&
verifier.VerifyString(location()) &&
verifier.EndTable();
verifier.VerifyString(location()) && verifier.EndTable();
}
};
@@ -266,14 +218,18 @@ struct FooBarContainerBuilder {
typedef FooBarContainer Table;
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_list(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list) {
void add_list(flatbuffers::Offset<flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>>
list) {
fbb_.AddOffset(FooBarContainer::VT_LIST, list);
}
void add_initialized(bool initialized) {
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED, static_cast<uint8_t>(initialized), 0);
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED,
static_cast<uint8_t>(initialized), 0);
}
void add_fruit(benchmarks_flatbuffers::Enum fruit) {
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT, static_cast<int16_t>(fruit), 0);
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT,
static_cast<int16_t>(fruit), 0);
}
void add_location(flatbuffers::Offset<flatbuffers::String> location) {
fbb_.AddOffset(FooBarContainer::VT_LOCATION, location);
@@ -291,7 +247,9 @@ struct FooBarContainerBuilder {
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list = 0,
flatbuffers::Offset<flatbuffers::Vector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>>
list = 0,
bool initialized = false,
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
flatbuffers::Offset<flatbuffers::String> location = 0) {
@@ -305,36 +263,41 @@ inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainerDirect(
flatbuffers::FlatBufferBuilder& _fbb,
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list = nullptr,
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>*
list = nullptr,
bool initialized = false,
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
const char* location = nullptr) {
auto list__ = list ? _fbb.CreateVector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list) : 0;
auto list__ =
list ? _fbb.CreateVector<
flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list)
: 0;
auto location__ = location ? _fbb.CreateString(location) : 0;
return benchmarks_flatbuffers::CreateFooBarContainer(
_fbb,
list__,
initialized,
fruit,
location__);
_fbb, list__, initialized, fruit, location__);
}
inline const benchmarks_flatbuffers::FooBarContainer *GetFooBarContainer(const void *buf) {
inline const benchmarks_flatbuffers::FooBarContainer* GetFooBarContainer(
const void* buf) {
return flatbuffers::GetRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
}
inline const benchmarks_flatbuffers::FooBarContainer *GetSizePrefixedFooBarContainer(const void *buf) {
return flatbuffers::GetSizePrefixedRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
inline const benchmarks_flatbuffers::FooBarContainer*
GetSizePrefixedFooBarContainer(const void* buf) {
return flatbuffers::GetSizePrefixedRoot<
benchmarks_flatbuffers::FooBarContainer>(buf);
}
inline bool VerifyFooBarContainerBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
inline bool VerifyFooBarContainerBuffer(flatbuffers::Verifier& verifier) {
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(
nullptr);
}
inline bool VerifySizePrefixedFooBarContainerBuffer(
flatbuffers::Verifier& verifier) {
return verifier.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
return verifier
.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(
nullptr);
}
inline void FinishFooBarContainerBuffer(

View File

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

View File

@@ -20,7 +20,7 @@ import PackageDescription
let package = Package(
name: "benchmarks",
platforms: [
.macOS(.v13),
.macOS(.v13)
],
dependencies: [
.package(path: "../.."),
@@ -37,6 +37,6 @@ let package = Package(
],
path: "Benchmarks/FlatbuffersBenchmarks",
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
.plugin(name: "BenchmarkPlugin", package: "package-benchmark")
])
])

View File

@@ -6,10 +6,11 @@ import subprocess
from cpt.packager import ConanMultiPackager
def get_branch():
try:
for line in subprocess.check_output("git branch", shell=True).decode().splitlines():
for line in (
subprocess.check_output("git branch", shell=True).decode().splitlines()
):
line = line.strip()
if line.startswith("*") and " (HEAD detached" not in line:
return line.replace("*", "", 1).strip()
@@ -34,17 +35,25 @@ def get_reference(username):
if __name__ == "__main__":
login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel")
username = os.getenv("CONAN_USERNAME", "google")
upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers")
stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*")
test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package"))
upload = os.getenv(
"CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers"
)
stable_branch_pattern = os.getenv(
"CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*"
)
test_folder = os.getenv(
"CPT_TEST_FOLDER", os.path.join("conan", "test_package")
)
upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
builder = ConanMultiPackager(reference=get_reference(username),
builder = ConanMultiPackager(
reference=get_reference(username),
username=username,
login_username=login_username,
upload=upload,
stable_branch_pattern=stable_branch_pattern,
upload_only_when_stable=upload_only_when_stable,
test_folder=test_folder)
test_folder=test_folder,
)
builder.add_common_builds(pure_c=False)
builder.run()

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from conans import ConanFile, CMake
import os
from conans import CMake, ConanFile
class TestPackageConan(ConanFile):

View File

@@ -1,11 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Conan recipe package for Google FlatBuffers
"""
"""Conan recipe package for Google FlatBuffers"""
import os
import shutil
from conans import ConanFile, CMake, tools
from conans import CMake, ConanFile, tools
class FlatbuffersConan(ConanFile):
@@ -21,23 +20,27 @@ class FlatbuffersConan(ConanFile):
default_options = {"shared": False, "fPIC": True}
generators = "cmake"
exports = "LICENSE"
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"]
exports_sources = [
"CMake/*",
"include/*",
"src/*",
"grpc/*",
"CMakeLists.txt",
"conan/CMakeLists.txt",
]
def source(self):
"""Wrap the original CMake file to call conan_basic_setup
"""
"""Wrap the original CMake file to call conan_basic_setup"""
shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt")
shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
def config_options(self):
"""Remove fPIC option on Windows platform
"""
"""Remove fPIC option on Windows platform"""
if self.settings.os == "Windows":
self.options.remove("fPIC")
def configure_cmake(self):
"""Create CMake instance and execute configure step
"""
"""Create CMake instance and execute configure step"""
cmake = CMake(self)
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
@@ -46,30 +49,35 @@ class FlatbuffersConan(ConanFile):
return cmake
def build(self):
"""Configure, build and install FlatBuffers using CMake.
"""
"""Configure, build and install FlatBuffers using CMake."""
cmake = self.configure_cmake()
cmake.build()
def package(self):
"""Copy Flatbuffers' artifacts to package folder
"""
"""Copy Flatbuffers' artifacts to package folder"""
cmake = self.configure_cmake()
cmake.install()
self.copy(pattern="LICENSE", dst="licenses")
self.copy(pattern="FindFlatBuffers.cmake", dst=os.path.join("lib", "cmake", "flatbuffers"), src="CMake")
self.copy(
pattern="FindFlatBuffers.cmake",
dst=os.path.join("lib", "cmake", "flatbuffers"),
src="CMake",
)
self.copy(pattern="flathash*", dst="bin", src="bin")
self.copy(pattern="flatc*", dst="bin", src="bin")
if self.settings.os == "Windows" and self.options.shared:
if self.settings.compiler == "Visual Studio":
shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "%s.dll" % self.name))
shutil.move(
os.path.join(self.package_folder, "lib", "%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "%s.dll" % self.name),
)
elif self.settings.compiler == "gcc":
shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name))
shutil.move(
os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name),
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name),
)
def package_info(self):
"""Collect built libraries names and solve flatc path.
"""
"""Collect built libraries names and solve flatc path."""
self.cpp_info.libs = tools.collect_libs(self)
self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,15 @@
import 'dart:typed_data';
import 'dart:io' as io;
import 'package:path/path.dart' as path;
import 'dart:typed_data';
import 'package:flat_buffers/flat_buffers.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import './monster_test_my_game.example_generated.dart' as example;
import './monster_test_my_game.example2_generated.dart' as example2;
import 'enums_generated.dart' as example3;
import './bool_structs_generated.dart' as example4;
import './monster_test_my_game.example2_generated.dart' as example2;
import './monster_test_my_game.example_generated.dart' as example;
import 'enums_generated.dart' as example3;
main() {
defineReflectiveSuite(() {
@@ -29,11 +28,9 @@ int indexToField(int index) {
@reflectiveTest
class CheckOtherLangaugesData {
test_cppData() async {
List<int> data = await io.File(path.join(
path.context.current,
'test',
'monsterdata_test.mon',
)).readAsBytes();
List<int> data = await io.File(
path.join(path.context.current, 'test', 'monsterdata_test.mon'),
).readAsBytes();
example.Monster mon = example.Monster(data);
expect(mon.hp, 80);
expect(mon.mana, 150);
@@ -145,7 +142,8 @@ class CheckOtherLangaugesData {
'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, '
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}');
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}',
);
}
}
@@ -298,20 +296,72 @@ class BuilderTest {
expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]);
builder.putUint8(3);
expect(
allocator.buffer(builder.size()), [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
0,
0,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint8(4);
expect(
allocator.buffer(builder.size()), [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
0,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint8(5);
expect(
allocator.buffer(builder.size()), [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
0,
5,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
builder.putUint32(6);
expect(allocator.buffer(builder.size()),
[6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
expect(allocator.buffer(builder.size()), [
6,
0,
0,
0,
0,
5,
4,
3,
2,
0,
0,
0,
0,
0,
0,
1,
]);
}
void test_table_default() {
@@ -331,14 +381,14 @@ class BuilderTest {
int objectOffset = buffer.derefObject(0);
// was not written, so uses the new default value
expect(
const Int32Reader()
.vTableGet(buffer, objectOffset, indexToField(0), 15),
15);
const Int32Reader().vTableGet(buffer, objectOffset, indexToField(0), 15),
15,
);
// has the written value
expect(
const Int32Reader()
.vTableGet(buffer, objectOffset, indexToField(1), 15),
20);
const Int32Reader().vTableGet(buffer, objectOffset, indexToField(1), 15),
20,
);
}
void test_table_format([Builder? builder]) {
@@ -370,7 +420,9 @@ class BuilderTest {
for (int i = 0; i < 3; i++) {
int offset = byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
expect(
byteData.getInt32(tableDataLoc + offset, Endian.little), 10 + 10 * i);
byteData.getInt32(tableDataLoc + offset, Endian.little),
10 + 10 * i,
);
}
}
@@ -380,10 +432,14 @@ class BuilderTest {
List<int> byteList;
{
Builder builder = Builder(initialSize: 0);
int? latinStringOffset =
builder.writeString(latinString, asciiOptimization: true);
int? unicodeStringOffset =
builder.writeString(unicodeString, asciiOptimization: true);
int? latinStringOffset = builder.writeString(
latinString,
asciiOptimization: true,
);
int? unicodeStringOffset = builder.writeString(
unicodeString,
asciiOptimization: true,
);
builder.startTable(2);
builder.addOffset(0, latinStringOffset);
builder.addOffset(1, unicodeStringOffset);
@@ -395,13 +451,19 @@ class BuilderTest {
BufferContext buf = BufferContext.fromBytes(byteList);
int objectOffset = buf.derefObject(0);
expect(
const StringReader()
.vTableGetNullable(buf, objectOffset, indexToField(0)),
latinString);
const StringReader().vTableGetNullable(
buf,
objectOffset,
indexToField(0),
),
latinString,
);
expect(
const StringReader(asciiOptimization: true)
.vTableGetNullable(buf, objectOffset, indexToField(1)),
unicodeString);
const StringReader(
asciiOptimization: true,
).vTableGetNullable(buf, objectOffset, indexToField(1)),
unicodeString,
);
}
void test_table_types([Builder? builder]) {
@@ -425,33 +487,41 @@ class BuilderTest {
BufferContext buf = BufferContext.fromBytes(byteList);
int objectOffset = buf.derefObject(0);
expect(
const BoolReader()
.vTableGetNullable(buf, objectOffset, indexToField(0)),
true);
const BoolReader().vTableGetNullable(buf, objectOffset, indexToField(0)),
true,
);
expect(
const Int8Reader()
.vTableGetNullable(buf, objectOffset, indexToField(1)),
10);
const Int8Reader().vTableGetNullable(buf, objectOffset, indexToField(1)),
10,
);
expect(
const Int32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(2)),
20);
const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(2)),
20,
);
expect(
const StringReader()
.vTableGetNullable(buf, objectOffset, indexToField(3)),
'12345');
const StringReader().vTableGetNullable(
buf,
objectOffset,
indexToField(3),
),
'12345',
);
expect(
const Int32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(4)),
40);
const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(4)),
40,
);
expect(
const Uint32Reader()
.vTableGetNullable(buf, objectOffset, indexToField(5)),
0x9ABCDEF0);
const Uint32Reader().vTableGetNullable(
buf,
objectOffset,
indexToField(5),
),
0x9ABCDEF0,
);
expect(
const Uint8Reader()
.vTableGetNullable(buf, objectOffset, indexToField(6)),
0x9A);
const Uint8Reader().vTableGetNullable(buf, objectOffset, indexToField(6)),
0x9A,
);
}
void test_writeList_of_Uint32() {
@@ -596,8 +666,9 @@ class BuilderTest {
}
// read and verify
BufferContext buf = BufferContext.fromBytes(byteList);
List<TestPointImpl> items =
const ListReader<TestPointImpl>(TestPointReader()).read(buf, 0);
List<TestPointImpl> items = const ListReader<TestPointImpl>(
TestPointReader(),
).read(buf, 0);
expect(items, hasLength(2));
expect(items[0].x, 10);
expect(items[0].y, 20);
@@ -627,8 +698,10 @@ class BuilderTest {
List<int> byteList;
{
builder ??= Builder(initialSize: 0);
int listOffset = builder.writeList(
[builder.writeString('12345'), builder.writeString('ABC')]);
int listOffset = builder.writeList([
builder.writeString('12345'),
builder.writeString('ABC'),
]);
builder.startTable(1);
builder.addOffset(0, listOffset);
int offset = builder.endTable();
@@ -707,13 +780,14 @@ class BuilderTest {
test_table_format,
test_table_types,
test_writeList_ofObjects,
test_writeList_ofStrings_inObject
test_writeList_ofStrings_inObject,
];
// Execute all test cases in all permutations of their order.
// To do that, we generate permutations of test case indexes.
final testCasesPermutations =
_permutationsOf(List.generate(testCases.length, (index) => index));
final testCasesPermutations = _permutationsOf(
List.generate(testCases.length, (index) => index),
);
expect(testCasesPermutations.length, _factorial(testCases.length));
for (var indexes in testCasesPermutations) {
@@ -788,7 +862,8 @@ class ObjectAPITest {
z: 3,
test1: 4.0,
test2: example.Color.Red,
test3: example.TestT(a: 1, b: 2))
test3: example.TestT(a: 1, b: 2),
)
..mana = 2
..name = 'Monstrous'
..inventory = [24, 42]
@@ -804,7 +879,7 @@ class ObjectAPITest {
..testf = 42.24
..testarrayofsortedstruct = [
example.AbilityT(id: 1, distance: 5),
example.AbilityT(id: 3, distance: 7)
example.AbilityT(id: 3, distance: 7),
]
..vectorOfLongs = [5, 6, 7]
..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2]
@@ -867,8 +942,9 @@ class StringListWrapperImpl {
StringListWrapperImpl(this.bp, this.offset);
List<String>? get items => const ListReader<String>(StringReader())
.vTableGetNullable(bp, offset, indexToField(0));
List<String>? get items => const ListReader<String>(
StringReader(),
).vTableGetNullable(bp, offset, indexToField(0));
}
class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
@@ -906,10 +982,14 @@ class GeneratorTest {
expect(example.Color.values, same(example.Color.values));
expect(example.Race.values, same(example.Race.values));
expect(example.AnyTypeId.values, same(example.AnyTypeId.values));
expect(example.AnyUniqueAliasesTypeId.values,
same(example.AnyUniqueAliasesTypeId.values));
expect(example.AnyAmbiguousAliasesTypeId.values,
same(example.AnyAmbiguousAliasesTypeId.values));
expect(
example.AnyUniqueAliasesTypeId.values,
same(example.AnyUniqueAliasesTypeId.values),
);
expect(
example.AnyAmbiguousAliasesTypeId.values,
same(example.AnyAmbiguousAliasesTypeId.values),
);
}
}
@@ -917,11 +997,13 @@ class GeneratorTest {
@reflectiveTest
class ListOfEnumsTest {
void test_listOfEnums() async {
var mytable = example3.MyTableObjectBuilder(options: [
var mytable = example3.MyTableObjectBuilder(
options: [
example3.OptionsEnum.A,
example3.OptionsEnum.B,
example3.OptionsEnum.C
]);
example3.OptionsEnum.C,
],
);
var bytes = mytable.toBytes();
var mytable_read = example3.MyTable(bytes);
expect(mytable_read.options![0].value, example3.OptionsEnum.A.value);
@@ -934,7 +1016,8 @@ class ListOfEnumsTest {
class BoolInStructTest {
void test_boolInStruct() async {
var mystruct = example4.FooObjectBuilder(
myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false));
myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false),
);
var bytes = mystruct.toBytes();
var mystruct_read = example4.Foo(bytes);
expect(mystruct_read.myFoo!.a, true);

View File

@@ -62,8 +62,23 @@ void main() {
{
var flx = Builder();
flx.addString('hello 😱');
expect(flx.finish(),
[10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]);
expect(flx.finish(), [
10,
104,
101,
108,
108,
111,
32,
240,
159,
152,
177,
0,
11,
20,
1,
]);
}
});
@@ -117,7 +132,7 @@ void main() {
192,
16,
75,
1
1,
]);
}
{
@@ -177,7 +192,7 @@ void main() {
7,
3,
60,
1
1,
]);
}
{
@@ -215,7 +230,7 @@ void main() {
10,
6,
60,
1
1,
]);
}
{
@@ -300,7 +315,7 @@ void main() {
104,
45,
43,
1
1,
]);
}
});
@@ -322,8 +337,24 @@ void main() {
..addKey('')
..addInt(45)
..end();
expect(
flx.finish(), [97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]);
expect(flx.finish(), [
97,
0,
0,
2,
2,
5,
2,
1,
2,
45,
12,
4,
4,
4,
36,
1,
]);
}
{
var flx = Builder()
@@ -367,7 +398,7 @@ void main() {
36,
4,
40,
1
1,
]);
}
});
@@ -381,21 +412,38 @@ void main() {
test('build from object', () {
expect(
Builder.buildFromObject(Uint8List.fromList([1, 2, 3]).buffer)
.asUint8List(),
[3, 1, 2, 3, 3, 100, 1]);
Builder.buildFromObject(
Uint8List.fromList([1, 2, 3]).buffer,
).asUint8List(),
[3, 1, 2, 3, 3, 100, 1],
);
expect(Builder.buildFromObject(null).asUint8List(), [0, 0, 1]);
expect(Builder.buildFromObject(true).asUint8List(), [1, 104, 1]);
expect(Builder.buildFromObject(false).asUint8List(), [0, 104, 1]);
expect(Builder.buildFromObject(25).asUint8List(), [25, 4, 1]);
expect(Builder.buildFromObject(-250).asUint8List(), [6, 255, 5, 2]);
expect(Builder.buildFromObject(-2.50).asUint8List(), [
0,
0,
32,
192,
14,
4,
]);
expect(Builder.buildFromObject('Maxim').asUint8List(), [
5,
77,
97,
120,
105,
109,
0,
6,
20,
1,
]);
expect(
Builder.buildFromObject(-2.50).asUint8List(), [0, 0, 32, 192, 14, 4]);
expect(Builder.buildFromObject('Maxim').asUint8List(),
[5, 77, 97, 120, 105, 109, 0, 6, 20, 1]);
expect(
Builder.buildFromObject([1, 3.3, 'max', true, null, false])
.asUint8List(),
Builder.buildFromObject([1, 3.3, 'max', true, null, false]).asUint8List(),
[
3,
109,
@@ -469,12 +517,13 @@ void main() {
104,
54,
43,
1
]);
1,
],
);
expect(
Builder.buildFromObject([
{'something': 12},
{'something': 45}
{'something': 45},
]).asUint8List(),
[
115,
@@ -506,8 +555,9 @@ void main() {
36,
4,
40,
1
]);
1,
],
);
});
test('add double indirectly', () {
@@ -543,7 +593,7 @@ void main() {
35,
8,
40,
1
1,
]);
});
@@ -580,7 +630,7 @@ void main() {
27,
8,
40,
1
1,
]);
});

View File

@@ -20,70 +20,76 @@ void main() {
expect(Reference.fromBuffer(b([1, 4, 5, 2])).intValue, 1025);
expect(Reference.fromBuffer(b([255, 251, 5, 2])).intValue, -1025);
expect(Reference.fromBuffer(b([1, 4, 9, 2])).intValue, 1025);
expect(Reference.fromBuffer(b([255, 255, 255, 127, 6, 4])).intValue,
2147483647);
expect(
Reference.fromBuffer(b([255, 255, 255, 127, 6, 4])).intValue,
2147483647,
);
expect(Reference.fromBuffer(b([0, 0, 0, 128, 6, 4])).intValue, -2147483648);
expect(
Reference.fromBuffer(b([255, 255, 255, 255, 0, 0, 0, 0, 7, 8]))
.intValue,
4294967295);
Reference.fromBuffer(b([255, 255, 255, 255, 0, 0, 0, 0, 7, 8])).intValue,
4294967295,
);
expect(
Reference.fromBuffer(b([255, 255, 255, 255, 255, 255, 255, 127, 7, 8]))
.intValue,
9223372036854775807);
expect(Reference.fromBuffer(b([0, 0, 0, 0, 0, 0, 0, 128, 7, 8])).intValue,
-9223372036854775808);
Reference.fromBuffer(
b([255, 255, 255, 255, 255, 255, 255, 127, 7, 8]),
).intValue,
9223372036854775807,
);
expect(
Reference.fromBuffer(b([0, 0, 0, 0, 0, 0, 0, 128, 7, 8])).intValue,
-9223372036854775808,
);
// Dart does not really support UInt64
// expect(FlxValue.fromBuffer(b([255, 255, 255, 255, 255, 255, 255, 255, 11, 8])).intValue, 18446744073709551615);
});
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([205, 204, 204, 61, 14, 4])).doubleValue,
closeTo(.1, .001));
expect(
Reference.fromBuffer(b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]))
.doubleValue,
.1);
Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).doubleValue,
closeTo(.1, .001),
);
expect(
Reference.fromBuffer(
b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]),
).doubleValue,
.1,
);
});
test('num value', () {
expect(Reference.fromBuffer(b([0, 0, 144, 64, 14, 4])).numValue, 4.5);
expect(Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).numValue,
closeTo(.1, .001));
expect(
Reference.fromBuffer(b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]))
.numValue,
.1);
Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).numValue,
closeTo(.1, .001),
);
expect(
Reference.fromBuffer(
b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]),
).numValue,
.1,
);
expect(Reference.fromBuffer(b([255, 251, 5, 2])).numValue, -1025);
});
test('string value', () {
expect(
Reference.fromBuffer(b([5, 77, 97, 120, 105, 109, 0, 6, 20, 1]))
.stringValue,
'Maxim');
Reference.fromBuffer(
b([5, 77, 97, 120, 105, 109, 0, 6, 20, 1]),
).stringValue,
'Maxim',
);
expect(
Reference.fromBuffer(b([
10,
104,
101,
108,
108,
111,
32,
240,
159,
152,
177,
0,
11,
20,
1
])).stringValue,
'hello 😱');
Reference.fromBuffer(
b([10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]),
).stringValue,
'hello 😱',
);
});
test('blob value', () {
expect(
Reference.fromBuffer(b([3, 1, 2, 3, 3, 100, 1])).blobValue, [1, 2, 3]);
expect(Reference.fromBuffer(b([3, 1, 2, 3, 3, 100, 1])).blobValue, [
1,
2,
3,
]);
});
test('bool vector', () {
var flx = Reference.fromBuffer(b([3, 1, 0, 1, 3, 144, 1]));
@@ -95,9 +101,12 @@ void main() {
testNumbers([3, 1, 2, 3, 3, 44, 1], [1, 2, 3]);
testNumbers([3, 255, 2, 3, 3, 44, 1], [-1, 2, 3]);
testNumbers([3, 0, 1, 0, 43, 2, 3, 0, 6, 45, 1], [1, 555, 3]);
testNumbers([3, 0, 0, 0, 1, 0, 0, 0, 204, 216, 0, 0, 3, 0, 0, 0, 12, 46, 1],
[1, 55500, 3]);
testNumbers([
testNumbers(
[3, 0, 0, 0, 1, 0, 0, 0, 204, 216, 0, 0, 3, 0, 0, 0, 12, 46, 1],
[1, 55500, 3],
);
testNumbers(
[
3,
0,
0,
@@ -132,16 +141,16 @@ void main() {
0,
24,
47,
1
], [
1,
55555555500,
3
]);
],
[1, 55555555500, 3],
);
testNumbers(
[3, 0, 0, 0, 0, 0, 192, 63, 0, 0, 32, 64, 0, 0, 96, 64, 12, 54, 1],
[1.5, 2.5, 3.5]);
testNumbers([
[1.5, 2.5, 3.5],
);
testNumbers(
[
3,
0,
0,
@@ -176,18 +185,17 @@ void main() {
64,
24,
55,
1
], [
1.1,
2.2,
3.3
]);
1,
],
[1.1, 2.2, 3.3],
);
});
test('number vector, fixed type', () {
testNumbers([1, 2, 2, 64, 1], [1, 2]);
testNumbers([255, 255, 0, 1, 4, 65, 1], [-1, 256]);
testNumbers([211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1], [-45, 256000]);
testNumbers([
testNumbers(
[
211,
255,
255,
@@ -206,18 +214,18 @@ void main() {
127,
16,
67,
1
], [
-45,
9223372036854775807
]);
1,
],
[-45, 9223372036854775807],
);
testNumbers([1, 2, 2, 68, 1], [1, 2]);
testNumbers([1, 0, 0, 1, 4, 69, 1], [1, 256]);
testNumbers([45, 0, 0, 0, 0, 232, 3, 0, 8, 70, 1], [45, 256000]);
testNumbers([205, 204, 140, 63, 0, 0, 0, 192, 8, 74, 1], [1.1, -2]);
testNumbers([
testNumbers(
[
154,
153,
153,
@@ -236,16 +244,18 @@ void main() {
192,
16,
75,
1
], [
1.1,
-256
]);
1,
],
[1.1, -256],
);
testNumbers([211, 255, 255, 255, 0, 232, 3, 0, 4, 0, 0, 0, 12, 78, 1],
[-45, 256000, 4]);
testNumbers(
[211, 255, 255, 255, 0, 232, 3, 0, 4, 0, 0, 0, 12, 78, 1],
[-45, 256000, 4],
);
testNumbers([
testNumbers(
[
211,
255,
255,
@@ -280,15 +290,13 @@ void main() {
0,
32,
91,
1
], [
-45,
9223372036854775807,
4,
9
]);
1,
],
[-45, 9223372036854775807, 4, 9],
);
testNumbers([
testNumbers(
[
45,
0,
0,
@@ -323,15 +331,13 @@ void main() {
0,
32,
95,
1
], [
45,
9223372036854775807,
4,
9
]);
1,
],
[45, 9223372036854775807, 4, 9],
);
testNumbers([
testNumbers(
[
154,
153,
153,
@@ -358,14 +364,13 @@ void main() {
64,
24,
87,
1
], [
1.1,
256,
4
]);
1,
],
[1.1, 256, 4],
);
testNumbers([
testNumbers(
[
154,
153,
153,
@@ -400,16 +405,14 @@ void main() {
64,
32,
99,
1
], [
1.1,
256,
4,
9
]);
1,
],
[1.1, 256, 4, 9],
);
});
test('string vector', () {
testStrings([
testStrings(
[
3,
102,
111,
@@ -431,13 +434,12 @@ void main() {
7,
3,
60,
1
], [
'foo',
'bar',
'baz'
]);
testStrings([
1,
],
['foo', 'bar', 'baz'],
);
testStrings(
[
3,
102,
111,
@@ -462,18 +464,14 @@ void main() {
10,
6,
60,
1
], [
'foo',
'bar',
'baz',
'foo',
'bar',
'baz'
]);
1,
],
['foo', 'bar', 'baz', 'foo', 'bar', 'baz'],
);
});
test('mixed vector', () {
var flx = Reference.fromBuffer(b([
var flx = Reference.fromBuffer(
b([
3,
102,
111,
@@ -537,8 +535,9 @@ void main() {
104,
45,
43,
1
]));
1,
]),
);
expect(flx.length, 5);
expect(flx[0].stringValue, 'foo');
expect(flx[1].numValue, 1);
@@ -554,7 +553,8 @@ void main() {
});
test('two value map', () {
var flx = Reference.fromBuffer(
b([0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]));
b([0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]),
);
expect(flx.length, 2);
expect(flx['a'].numValue, 12);
expect(flx[''].numValue, 45);
@@ -579,54 +579,89 @@ void main() {
expect(
() => flx['address']['country'].stringValue,
throwsA(predicate((dynamic e) =>
throwsA(
predicate(
(dynamic e) =>
e is ArgumentError &&
e.message ==
'Key: [country] is not applicable on: //address of: ValueType.Map')));
'Key: [country] is not applicable on: //address of: ValueType.Map',
),
),
);
expect(
() => flx['address']['countryCode'][0],
throwsA(predicate((dynamic e) =>
throwsA(
predicate(
(dynamic e) =>
e is ArgumentError &&
e.message ==
'Key: [0] is not applicable on: //address/countryCode of: ValueType.String')));
'Key: [0] is not applicable on: //address/countryCode of: ValueType.String',
),
),
);
expect(
() => flx[1],
throwsA(predicate((dynamic e) =>
throwsA(
predicate(
(dynamic e) =>
e is ArgumentError &&
e.message ==
'Key: [1] is not applicable on: / of: ValueType.Map')));
e.message == 'Key: [1] is not applicable on: / of: ValueType.Map',
),
),
);
expect(
() => flx['flags'][4],
throwsA(predicate((dynamic e) =>
throwsA(
predicate(
(dynamic e) =>
e is ArgumentError &&
e.message ==
'Key: [4] is not applicable on: //flags of: ValueType.VectorBool length: 4')));
'Key: [4] is not applicable on: //flags of: ValueType.VectorBool length: 4',
),
),
);
expect(
() => flx['flags'][-1],
throwsA(predicate((dynamic e) =>
throwsA(
predicate(
(dynamic e) =>
e is ArgumentError &&
e.message ==
'Key: [-1] is not applicable on: //flags of: ValueType.VectorBool length: 4')));
'Key: [-1] is not applicable on: //flags of: ValueType.VectorBool length: 4',
),
),
);
});
test('complex map to json', () {
var flx = complexMap();
expect(flx.json,
'{"address":{"city":"Bla","countryCode":"XX","zip":"12345"},"age":35,"flags":[true,false,true,true],"name":"Maxim","weight":72.5}');
expect(
flx.json,
'{"address":{"city":"Bla","countryCode":"XX","zip":"12345"},"age":35,"flags":[true,false,true,true],"name":"Maxim","weight":72.5}',
);
});
test('complex map iterators', () {
var flx = complexMap();
expect(flx.mapKeyIterable.map((e) => e).toList(),
['address', 'age', 'flags', 'name', 'weight']);
expect(flx.mapKeyIterable.map((e) => e).toList(), [
'address',
'age',
'flags',
'name',
'weight',
]);
expect(flx.mapValueIterable.map((e) => e.json).toList(), [
flx['address'].json,
flx['age'].json,
flx['flags'].json,
flx['name'].json,
flx['weight'].json
flx['weight'].json,
]);
expect(flx['flags'].vectorIterable.map((e) => e.boolValue).toList(), [
true,
false,
true,
true,
]);
expect(flx['flags'].vectorIterable.map((e) => e.boolValue).toList(),
[true, false, true, true]);
});
test('bug where offest were stored as int instead of uint', () {
@@ -790,11 +825,13 @@ void main() {
4,
16,
36,
1
1,
];
var flx = Reference.fromBuffer(b(data));
expect(flx.json,
'{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}');
expect(
flx.json,
'{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}',
);
const object = {
"channels_in": 64,
"dilation_height_factor": 1,
@@ -803,13 +840,15 @@ void main() {
"pad_values": 1,
"padding": 0,
"stride_height": 1,
"stride_width": 1
"stride_width": 1,
};
var data1 = Builder.buildFromObject(object).asUint8List();
expect(data1.length, data.length);
var flx1 = Reference.fromBuffer(b(data1));
expect(flx1.json,
'{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}');
expect(
flx1.json,
'{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}',
);
});
}
@@ -846,7 +885,8 @@ Reference complexMap() {
// "countryCode": "XX",
// }
// }
return Reference.fromBuffer(b([
return Reference.fromBuffer(
b([
97,
100,
100,
@@ -986,6 +1026,7 @@ Reference complexMap() {
14,
25,
38,
1
]));
1,
]),
);
}

View File

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

View File

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

View File

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

View File

@@ -4,12 +4,12 @@
library my_game.example2;
import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_test_my_game_generated.dart' as my_game;
import './monster_test_my_game.example_generated.dart' as my_game_example;
import './include_test1_generated.dart';
import './monster_test_my_game.example_generated.dart' as my_game_example;
import './monster_test_my_game_generated.dart' as my_game;
class Monster {
Monster._(this._bc, this._bcOffset);
@@ -23,7 +23,6 @@ class Monster {
final fb.BufferContext _bc;
final int _bcOffset;
@override
String toString() {
return 'Monster{}';
@@ -59,7 +58,6 @@ class _MonsterReader extends fb.TableReader<Monster> {
}
class MonsterObjectBuilder extends fb.ObjectBuilder {
MonsterObjectBuilder();
/// Finish building, and store into the [fbBuilder].

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -6,7 +6,7 @@ https://flatbuffers.dev.
## Local Building
The documentation can be built and served locally during development, see [https//flatbuffers.dev/contributing/#local-development] for full details.
The documentation can be built and served locally during development, see <https://flatbuffers.dev/contributing/#local-development> for full details.
__tl;dr__

View File

@@ -139,7 +139,7 @@ nav:
- Dart: "languages/dart.md"
- Go: "languages/go.md"
- Java: "languages/java.md"
- JavasScript: "languages/javascript.md"
- JavaScript: "languages/javascript.md"
- Kotlin: "languages/kotlin.md"
- Lobster: "languages/lobster.md"
- Lua: "languages/lua.md"

View File

@@ -131,7 +131,7 @@ list of `FILES...`.
- `--gen-mutable` : Generate additional non-const accessors for mutating
FlatBuffers in-place.
- `--gen-onefile` : Generate single output file for C#, Go, and Python.
- `--gen-onefile` : Generate a single output file for C#, Go, Java, Kotlin and Python.
- `--gen-name-strings` : Generate type name functions for C++.
@@ -259,6 +259,8 @@ list of `FILES...`.
- `--python-typing` : Generate Python type annotations
- `--python-decode-obj-api-strings` : Decode bytes automaticaly with utf-8
Additional gRPC options:
- `--grpc-filename-suffix`: `[C++]` An optional suffix for the generated

View File

@@ -21,15 +21,15 @@ It is available as Open Source on
- :material-memory:{ .lg .middle } **Memory Efficiency and Speed**
---
The only memory needed to access your data is that of the buffer. No heap is
required.
The only memory needed to access your data is that of the buffer.
No heap is required.
- :material-compare-horizontal:{ .lg .middle } **Backwards and Forwards
Compatibility**
---
The only memory needed to access your data is that of the buffer. No heap is
required.
FlatBuffers enables the schema to evolve over time while still maintaining
forwards and backwards compatibility with old flatbuffers.
- :material-scale-off:{ .lg .middle } **Small Footprint**

View File

@@ -419,7 +419,8 @@ Each root type will have a verification function generated for it,
e.g. for `Monster`, you can call:
```cpp
bool ok = VerifyMonsterBuffer(Verifier(buf, len));
Verifier verifier(buf, len);
bool ok = VerifyMonsterBuffer(verifier);
```
if `ok` is true, the buffer is safe to read.

View File

@@ -48,7 +48,7 @@ function). Then you can read a FlatBuffer binary file, which you
pass the contents of to the `GetRootAsMonster` function:
~~~{.php}
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
// It is recommended that you use PSR autoload when using FlatBuffers in PHP.
// Here is an example:
function __autoload($class_name) {
// The last segment of the class name matches the file name.
@@ -69,7 +69,7 @@ pass the contents of to the `GetRootAsMonster` function:
// Read the contents of the FlatBuffer binary file.
$filename = "monster.dat";
$handle = fopen($filename, "rb");
$contents = $fread($handle, filesize($filename));
$contents = fread($handle, filesize($filename));
fclose($handle);
// Pass the contents to `GetRootAsMonster`.

View File

@@ -177,6 +177,34 @@ functions require a mutable (aka exclusive) reference which can only be created
when no other references to the `FlatBufferBuilder` exist, and may not be copied
within the same thread, let alone to a second thread.
## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to
read and write data even if you don't know the exact format of a buffer, and
even allows you to change sizes of strings in-place.
The way this works is very elegant; there is actually a FlatBuffer schema that
describes schemas (\!) which you can find in `reflection/reflection.fbs`.
The compiler, `flatc`, can write out any schemas it has just parsed as a binary
FlatBuffer, corresponding to this meta-schema.
Loading in one of these binary schemas at runtime allows you to traverse any
FlatBuffer data that corresponds to it without knowing the exact format. You
can query what fields are present, and then read/write them after.
For convenient field manipulation, you can use the crate
`flatbuffers-reflection` which includes both the generated code from the meta
schema, as well as a lot of helper functions.
And example of usage, for the time being, can be found in
`tests/rust_reflection_test/src/lib.rs`. Two sets of APIs are provided:
- [Unsafe getters/setters](https://docs.rs/flatbuffers-reflection/latest/flatbuffers_reflection/#functions),
which you can use when you are processing trusted data (either from a source you know, or has been verified)
- Safe getters in [SafeBuffer](https://docs.rs/flatbuffers-reflection/latest/flatbuffers_reflection/struct.SafeBuffer.html),
which does verification when constructed so you can use it for any data source
## Useful tools created by others
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler

View File

@@ -57,7 +57,7 @@ a data object from the server, which you can pass into the `GetRootAsMonster` fu
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
guard let data = try? Data(contentsOf: url) else { return }
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:

View File

@@ -30,7 +30,7 @@ See the [Tutorial](tutorial.md) for a more in depth guide.
code:
```sh
./flatc --cpp --rust mosnter.fbs
./flatc --cpp --rust monster.fbs
```
Which generates `monster_generated.h` and `monster_generated.rs` files.

View File

@@ -2011,6 +2011,8 @@ like so:
let buf = builder.sizedByteArray
// or you can use to get an object of type Data
let bufData = ByteBuffer(data: builder.data)
// or
let buf = builder.sizedBuffer
```
=== "TypeScript"

10
eslint.config.mjs Normal file
View File

@@ -0,0 +1,10 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
export default [
{files: ["**/*.{js,mjs,cjs,ts}"]},
{languageOptions: { globals: {...globals.browser, ...globals.node} }},
pluginJs.configs.recommended,
...tseslint.configs.recommended,
];

View File

@@ -104,13 +104,16 @@ func (b *Builder) StartObject(numfields int) {
// logically-equal vtables will be deduplicated.
//
// A vtable has the following format:
//
// <VOffsetT: size of the vtable in bytes, including this value>
// <VOffsetT: size of the object in bytes, including the vtable offset>
// <VOffsetT: offset for a field> * N, where N is the number of fields in
// the schema for this type. Includes deprecated fields.
//
// Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide.
//
// An object has the following format:
//
// <SOffsetT: offset to this object's vtable (may be negative)>
// <byte: data>+
func (b *Builder) WriteVtable() (n UOffsetT) {
@@ -296,6 +299,7 @@ func (b *Builder) PrependUOffsetT(off UOffsetT) {
// StartVector initializes bookkeeping for writing a new vector.
//
// A vector has the following format:
//
// <UOffsetT: number of elements in this vector>
// <T: data>+, where T is the type of elements of this vector.
func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT {

View File

@@ -1,7 +1,17 @@
package flatbuffers
import "errors"
var (
// Codec implements gRPC-go Codec which is used to encode and decode messages.
var Codec = "flatbuffers"
Codec = "flatbuffers"
// ErrInsufficientData is returned when the data is too short to read the root UOffsetT.
ErrInsufficientData = errors.New("insufficient data")
// ErrInvalidRootOffset is returned when the root UOffsetT is out of bounds.
ErrInvalidRootOffset = errors.New("invalid root offset")
)
// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
// that implementations of this interface must be thread safe; a Codec's
@@ -15,7 +25,21 @@ func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
// Unmarshal parses the wire format into v.
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
// Need at least 4 bytes to read the root table offset (UOffsetT).
// Vtable soffset_t and metadata are read later during field access.
if len(data) < SizeUOffsetT {
return ErrInsufficientData
}
off := GetUOffsetT(data)
// The root UOffsetT must be within the data buffer
// Compare in the unsigned domain to avoid signedness pitfalls
if off > UOffsetT(len(data)-SizeUOffsetT) {
return ErrInvalidRootOffset
}
v.(flatbuffersInit).Init(data, off)
return nil
}

View File

@@ -3,8 +3,8 @@
This directory is a repository for the generated files of `flatc`.
We check in the generated code so we can see, during a PR review, how the
changes affect the generated output. Its also useful as a reference to point too
as how things work across various languages.
changes affect the generated output. It's also useful as a reference to show
how things work across various languages.
These files are **NOT** intended to be depended on by any code, such as tests or
or compiled examples.

View File

@@ -9,8 +9,8 @@
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
FLATBUFFERS_VERSION_MINOR == 2 &&
FLATBUFFERS_VERSION_REVISION == 10,
FLATBUFFERS_VERSION_MINOR == 9 &&
FLATBUFFERS_VERSION_REVISION == 23,
"Non-compatible flatbuffers version included");
namespace flatbuffers {

View File

@@ -13,7 +13,7 @@ public struct Galaxy : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_9_23(); }
public static Galaxy GetRootAsGalaxy(ByteBuffer _bb) { return GetRootAsGalaxy(_bb, new Galaxy()); }
public static Galaxy GetRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }

View File

@@ -13,7 +13,7 @@ public struct Universe : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_9_23(); }
public static Universe GetRootAsUniverse(ByteBuffer _bb) { return GetRootAsUniverse(_bb, new Universe()); }
public static Universe GetRootAsUniverse(ByteBuffer _bb, Universe obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool VerifyUniverse(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, UniverseVerify.Verify); }

View File

@@ -1,5 +1,5 @@
import sys
from pathlib import Path
import sys
# Get the path where this script is located so we can invoke the script from
# any directory and have the paths work correctly.

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused")
public final class Galaxy extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_25_2_10(); }
public static void ValidateVersion() { Constants.FLATBUFFERS_25_9_23(); }
public static Galaxy getRootAsGalaxy(ByteBuffer _bb) { return getRootAsGalaxy(_bb, new Galaxy()); }
public static Galaxy getRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused")
public final class Universe extends Table {
public static void ValidateVersion() { Constants.FLATBUFFERS_25_2_10(); }
public static void ValidateVersion() { Constants.FLATBUFFERS_25_9_23(); }
public static Universe getRootAsUniverse(ByteBuffer _bb) { return getRootAsUniverse(_bb, new Universe()); }
public static Universe getRootAsUniverse(ByteBuffer _bb, Universe obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -34,7 +34,7 @@ class Galaxy : Table() {
return if(o != 0) bb.getLong(o + bb_pos) else 0L
}
companion object {
fun validateVersion() = Constants.FLATBUFFERS_25_2_10()
fun validateVersion() = Constants.FLATBUFFERS_25_9_23()
fun getRootAsGalaxy(_bb: ByteBuffer): Galaxy = getRootAsGalaxy(_bb, Galaxy())
fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy {
_bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -47,7 +47,7 @@ class Universe : Table() {
val o = __offset(6); return if (o != 0) __vector_len(o) else 0
}
companion object {
fun validateVersion() = Constants.FLATBUFFERS_25_2_10()
fun validateVersion() = Constants.FLATBUFFERS_25_9_23()
fun getRootAsUniverse(_bb: ByteBuffer): Universe = getRootAsUniverse(_bb, Universe())
fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe {
_bb.order(ByteOrder.LITTLE_ENDIAN)

View File

@@ -37,7 +37,7 @@ impl<'a> flatbuffers::Follow<'a> for Galaxy<'a> {
type Inner = Galaxy<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table::new(buf, loc) }
Self { _tab: unsafe { flatbuffers::Table::new(buf, loc) } }
}
}
@@ -134,7 +134,7 @@ impl<'a> flatbuffers::Follow<'a> for Universe<'a> {
type Inner = Universe<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: flatbuffers::Table::new(buf, loc) }
Self { _tab: unsafe { flatbuffers::Table::new(buf, loc) } }
}
}
@@ -288,14 +288,14 @@ pub fn size_prefixed_root_as_universe_with_opts<'b, 'o>(
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Universe`.
pub unsafe fn root_as_universe_unchecked(buf: &[u8]) -> Universe {
flatbuffers::root_unchecked::<Universe>(buf)
unsafe { flatbuffers::root_unchecked::<Universe>(buf) }
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Universe and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Universe`.
pub unsafe fn size_prefixed_root_as_universe_unchecked(buf: &[u8]) -> Universe {
flatbuffers::size_prefixed_root_unchecked::<Universe>(buf)
unsafe { flatbuffers::size_prefixed_root_unchecked::<Universe>(buf) }
}
#[inline]
pub fn finish_universe_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>(

View File

@@ -2,11 +2,15 @@
// swiftlint:disable all
// swiftformat:disable all
#if canImport(Common)
import Common
#endif
import FlatBuffers
public struct flatbuffers_goldens_Galaxy: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_2_10() }
static func validateVersion() { FlatBuffersVersion_25_9_23() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
@@ -41,7 +45,7 @@ public struct flatbuffers_goldens_Galaxy: FlatBufferObject, Verifiable {
public struct flatbuffers_goldens_Universe: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_2_10() }
static func validateVersion() { FlatBuffersVersion_25_9_23() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table

View File

@@ -1,5 +1,4 @@
GRPC implementation and test
============================
NOTE: files in `src/` are shared with the GRPC project, and maintained there
(any changes should be submitted to GRPC instead). These files are copied
@@ -40,3 +39,63 @@ For Bazel users:
```shell
$bazel test tests/...
```
## C++ Callback API Generation
FlatBuffers gRPC C++ code generation now optionally supports the modern gRPC Callback API.
To enable generation of a `CallbackService` skeleton alongside the existing `Service` and async mixins, invoke `flatc` with both `--grpc` and `--grpc-callback-api`:
```shell
flatc --cpp --grpc --grpc-callback-api your_service.fbs
```
This adds (guarded by `#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)`) a class:
```cpp
class YourService::CallbackService : public ::grpc::Service { /* reactor virtuals */ };
```
Each RPC shape maps to the appropriate reactor return type:
- Unary -> `::grpc::ServerUnaryReactor*` Method(...)
- Client streaming -> `::grpc::ServerReadReactor<Request>*`
- Server streaming -> `::grpc::ServerWriteReactor<Response>*`
- Bidi streaming -> `::grpc::ServerBidiReactor<Request, Response>*`
Default generated implementations return `nullptr`; override in your derived class and return a reactor instance you manage (see gRPC docs for lifecycle patterns).
If your gRPC library predates the stable callback API macro, the code inside the guard will be skipped (no breaking changes). Ensure you build against a recent gRPC (1.38+; verify current minimum in grpc repo) to use this feature.
### Client Callback Stubs
When `--grpc-callback-api` is supplied, the generated C++ client stub gains native callback / reactor based async methods in addition to the existing synchronous / generic async flavors, guarded by the same macro. For each RPC named `Foo`:
Unary:
```
void async_Foo(::grpc::ClientContext*, const Request&, Response*, std::function<void(::grpc::Status)>);
void async_Foo(::grpc::ClientContext*, const Request&, Response*, ::grpc::ClientUnaryReactor*);
```
Client streaming:
```
::grpc::ClientWriteReactor<Request>* async_Foo(::grpc::ClientContext*, Response*, ::grpc::ClientWriteReactor<Request>*);
```
Server streaming:
```
::grpc::ClientReadReactor<Response>* async_Foo(::grpc::ClientContext*, const Request&, ::grpc::ClientReadReactor<Response>*);
```
Bidirectional streaming:
```
::grpc::ClientBidiReactor<Request, Response>* async_Foo(::grpc::ClientContext*, ::grpc::ClientBidiReactor<Request, Response>*);
```
These map directly onto the native gRPC callback API factories (e.g. `CallbackUnaryCall`, `ClientCallbackWriterFactory::Create`, etc.) and do not spawn threads. Override the appropriate reactor callbacks per gRPC's documentation to drive I/O.
If your build uses an older gRPC lacking the non-experimental macro, these symbols will not be emitted, preserving backwards compatibility.

View File

@@ -1,31 +1,36 @@
import sys
import argparse
import sys
import grpc
sys.path.insert(0, '../../../../../flatbuffers/python')
sys.path.insert(0, "../../../../../flatbuffers/python")
import flatbuffers
from models import HelloReply, HelloRequest, greeter_grpc_fb
parser = argparse.ArgumentParser()
parser.add_argument("port", help="server port to connect to", default=3000)
parser.add_argument("name", help="name to be sent to server", default="flatbuffers")
parser.add_argument(
"name", help="name to be sent to server", default="flatbuffers"
)
def say_hello(stub, hello_request):
reply = stub.SayHello(hello_request)
r = HelloReply.HelloReply.GetRootAs(reply)
print(r.Message())
def say_many_hellos(stub, hello_request):
greetings = stub.SayManyHellos(hello_request)
for greeting in greetings:
r = HelloReply.HelloReply.GetRootAs(greeting)
print(r.Message())
def main():
args = parser.parse_args()
with grpc.insecure_channel('localhost:' + args.port) as channel:
with grpc.insecure_channel("localhost:" + args.port) as channel:
builder = flatbuffers.Builder()
ind = builder.CreateString(args.name)
HelloRequest.HelloRequestStart(builder)
@@ -37,4 +42,5 @@ def main():
say_hello(stub, output)
say_many_hellos(stub, output)
main()

View File

@@ -2,30 +2,29 @@
import flatbuffers
import grpc
from models.HelloReply import HelloReply
from models.HelloRequest import HelloRequest
class GreeterStub(object):
'''Interface exported by the server.'''
"""Interface exported by the server."""
def __init__(self, channel):
'''Constructor.
"""Constructor.
Args:
channel: A grpc.Channel.
'''
"""
self.SayHello = channel.unary_unary(
method='/models.Greeter/SayHello')
self.SayHello = channel.unary_unary(method='/models.Greeter/SayHello')
self.SayManyHellos = channel.unary_stream(
method='/models.Greeter/SayManyHellos')
method='/models.Greeter/SayManyHellos'
)
class GreeterServicer(object):
'''Interface exported by the server.'''
"""Interface exported by the server."""
def SayHello(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
@@ -40,15 +39,14 @@ class GreeterServicer(object):
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello),
'SayHello': grpc.unary_unary_rpc_method_handler(servicer.SayHello),
'SayManyHellos': grpc.unary_stream_rpc_method_handler(
servicer.SayManyHellos),
servicer.SayManyHellos
),
}
generic_handler = grpc.method_handlers_generic_handler(
'models.Greeter', rpc_method_handlers)
'models.Greeter', rpc_method_handlers
)
server.add_generic_rpc_handlers((generic_handler,))

View File

@@ -1,52 +1,54 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!
import flatbuffers
import grpc
from models.HelloReply import HelloReply
from models.HelloRequest import HelloRequest
class GreeterStub(object):
""" Interface exported by the server. """
'''Interface exported by the server.'''
def __init__(self, channel):
""" Constructor.
'''Constructor.
Args:
channel: A grpc.Channel.
"""
'''
self.SayHello = channel.unary_unary(
"/models.Greeter/SayHello"
)
method='/models.Greeter/SayHello')
self.SayManyHellos = channel.unary_stream(
"/models.Greeter/SayManyHellos"
)
method='/models.Greeter/SayManyHellos')
class GreeterServicer(object):
""" Interface exported by the server. """
'''Interface exported by the server.'''
def SayHello(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SayManyHellos(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello
),
servicer.SayHello),
'SayManyHellos': grpc.unary_stream_rpc_method_handler(
servicer.SayManyHellos
),
servicer.SayManyHellos),
}
generic_handler = grpc.method_handlers_generic_handler(
'models.Greeter', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))

View File

@@ -1,9 +1,9 @@
import argparse
from concurrent import futures
import sys
import argparse
import grpc
sys.path.insert(0, '../../../../../flatbuffers/python')
sys.path.insert(0, "../../../../../flatbuffers/python")
import flatbuffers
from models import HelloReply, HelloRequest, greeter_grpc_fb
@@ -11,6 +11,7 @@ from models import HelloReply, HelloRequest, greeter_grpc_fb
parser = argparse.ArgumentParser()
parser.add_argument("port", help="server on port", default=3000)
def build_reply(message):
builder = flatbuffers.Builder()
ind = builder.CreateString(message)
@@ -20,6 +21,7 @@ def build_reply(message):
builder.Finish(root)
return bytes(builder.Output())
class GreeterServicer(greeter_grpc_fb.GreeterServicer):
def __init__(self):
@@ -30,7 +32,7 @@ class GreeterServicer(greeter_grpc_fb.GreeterServicer):
reply = "Unknown"
if r.Name():
reply = r.Name()
return build_reply("welcome " + reply.decode('UTF-8'))
return build_reply("welcome " + reply.decode("UTF-8"))
def SayManyHellos(self, request, context):
r = HelloRequest.HelloRequest().GetRootAs(request, 0)
@@ -40,18 +42,17 @@ class GreeterServicer(greeter_grpc_fb.GreeterServicer):
for greeting in self.greetings:
print(type(reply))
yield build_reply(greeting + " " + reply.decode('UTF-8'))
yield build_reply(greeting + " " + reply.decode("UTF-8"))
def serve():
args = parser.parse_args()
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
greeter_grpc_fb.add_GreeterServicer_to_server(
GreeterServicer(), server
)
server.add_insecure_port('[::]:' + args.port)
greeter_grpc_fb.add_GreeterServicer_to_server(GreeterServicer(), server)
server.add_insecure_port("[::]:" + args.port)
server.start()
server.wait_for_termination()
if __name__ == '__main__':
if __name__ == "__main__":
serve()

View File

@@ -20,7 +20,7 @@ import PackageDescription
let package = Package(
name: "Greeter",
platforms: [
.iOS(.v11),
.iOS(.v12),
.macOS(.v10_14),
],
dependencies: [

View File

@@ -5,6 +5,7 @@
// swiftlint:disable all
// swiftformat:disable all
#if !os(Windows)
import Foundation
import GRPC
import NIO
@@ -17,8 +18,7 @@ public extension GRPCFlatBufPayload {
self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: serializedByteBuffer.readableBytesView, count: serializedByteBuffer.readableBytes))
}
func serialize(into buffer: inout NIO.ByteBuffer) throws {
let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: Int(self.size))
buffer.writeBytes(buf)
withUnsafeReadableBytes { buffer.writeBytes($0) }
}
}
extension Message: GRPCFlatBufPayload {}
@@ -143,3 +143,5 @@ public protocol models_GreeterServerInterceptorFactoryProtocol {
func makeSayManyHellosInterceptors() -> [ServerInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
}
#endif

View File

@@ -2,11 +2,15 @@
// swiftlint:disable all
// swiftformat:disable all
#if canImport(Common)
import Common
#endif
import FlatBuffers
public struct models_HelloReply: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_2_10() }
static func validateVersion() { FlatBuffersVersion_25_9_23() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
@@ -53,7 +57,7 @@ extension models_HelloReply: Encodable {
public struct models_HelloRequest: FlatBufferObject, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_2_10() }
static func validateVersion() { FlatBuffersVersion_25_9_23() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table

View File

@@ -37,7 +37,8 @@ func greet(name: String, client greeter: models_GreeterServiceClient) {
builder.finish(offset: root)
// Make the RPC call to the server.
let sayHello = greeter
let sayHello =
greeter
.SayHello(Message<models_HelloRequest>(builder: &builder))
// wait() on the response to stop the program from exiting before the response is received.
@@ -76,7 +77,7 @@ func main(args: [String]) {
print("Usage: PORT [NAME]")
exit(1)
case let (.some(port), name):
case (.some(let port), let name):
// Setup an `EventLoopGroup` for the connection to run on.
//
// See: https://github.com/apple/swift-nio#eventloops-and-eventloopgroups

View File

@@ -32,7 +32,8 @@ class Greeter: models_GreeterProvider {
func SayHello(
request: Message<models_HelloRequest>,
context: StatusOnlyCallContext)
context: StatusOnlyCallContext
)
-> EventLoopFuture<Message<models_HelloReply>>
{
let recipient = request.object.name ?? "Stranger"
@@ -47,12 +48,14 @@ class Greeter: models_GreeterProvider {
func SayManyHellos(
request: Message<models_HelloRequest>,
context: StreamingResponseCallContext<Message<models_HelloReply>>)
context: StreamingResponseCallContext<Message<models_HelloReply>>
)
-> EventLoopFuture<GRPCStatus>
{
for name in greetings {
var builder = FlatBufferBuilder()
let off = builder
let off =
builder
.create(string: "\(name) \(request.object.name ?? "Unknown")")
let root = models_HelloReply.createHelloReply(
&builder,

View File

@@ -1,16 +1,21 @@
import * as grpc from '@grpc/grpc-js';
import * as flatbuffers from 'flatbuffers';
import {GreeterClient} from './greeter_grpc';
import {HelloReply} from './models/hello-reply';
import {HelloRequest} from './models/hello-request';
import { GreeterClient } from './greeter_grpc';
async function main(PORT: Number, name: string) {
const client = new GreeterClient(`localhost:${PORT}`, grpc.credentials.createInsecure());
const client = new GreeterClient(
`localhost:${PORT}`,
grpc.credentials.createInsecure(),
);
const builder = new flatbuffers.Builder();
const offset = builder.createString(name);
const root = HelloRequest.createHelloRequest(builder, offset);
builder.finish(root);
const buffer = HelloRequest.getRootAsHelloRequest(new flatbuffers.ByteBuffer(builder.asUint8Array()));
const buffer = HelloRequest.getRootAsHelloRequest(
new flatbuffers.ByteBuffer(builder.asUint8Array()),
);
client.SayHello(buffer, (err, response) => {
console.log(response.message());
@@ -23,12 +28,12 @@ async function main(PORT: Number, name: string) {
});
}
const args = process.argv.slice(2)
const args = process.argv.slice(2);
const PORT = Number(args[0]);
const name: string = args[1] ?? "flatbuffers";
const name: string = args[1] ?? 'flatbuffers';
if (PORT) {
main(PORT, name);
} else {
throw new Error("Requires a valid port number.")
throw new Error('Requires a valid port number.');
}

View File

@@ -1,31 +1,45 @@
import * as grpc from '@grpc/grpc-js';
import * as flatbuffers from 'flatbuffers';
import {GreeterService, IGreeterServer} from './greeter_grpc';
import {HelloReply} from './models/hello-reply';
import {HelloRequest} from './models/hello-request';
import { IGreeterServer, GreeterService } from './greeter_grpc';
const greeter: IGreeterServer = {
SayHello(call: grpc.ServerUnaryCall<HelloRequest, HelloReply>, callback: grpc.sendUnaryData<HelloReply>): void {
SayHello(
call: grpc.ServerUnaryCall<HelloRequest, HelloReply>,
callback: grpc.sendUnaryData<HelloReply>,
): void {
console.log(`SayHello ${call.request.name()}`);
const builder = new flatbuffers.Builder();
const offset = builder.createString(`welcome ${call.request.name()}`);
const root = HelloReply.createHelloReply(builder, offset);
builder.finish(root);
callback(null, HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array())));
callback(
null,
HelloReply.getRootAsHelloReply(
new flatbuffers.ByteBuffer(builder.asUint8Array()),
),
);
},
async SayManyHellos(call: grpc.ServerWritableStream<HelloRequest, HelloReply>): Promise<void> {
async SayManyHellos(
call: grpc.ServerWritableStream<HelloRequest, HelloReply>,
): Promise<void> {
const name = call.request.name();
console.log(`${call.request.name()} saying hi in different langagues`);
['Hi', 'Hallo', 'Ciao'].forEach(element => {
['Hi', 'Hallo', 'Ciao'].forEach((element) => {
const builder = new flatbuffers.Builder();
const offset = builder.createString(`${element} ${name}`);
const root = HelloReply.createHelloReply(builder, offset);
builder.finish(root);
call.write(HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array())))
call.write(
HelloReply.getRootAsHelloReply(
new flatbuffers.ByteBuffer(builder.asUint8Array()),
),
);
});
call.end();
}
}
},
};
function serve(): void {
const PORT = 3000;
@@ -42,7 +56,7 @@ function serve(): void {
console.log(`Server bound on port: ${port}`);
server.start();
}
}
},
);
}

View File

@@ -19,16 +19,15 @@ import com.google.flatbuffers.Table;
import io.grpc.Drainable;
import io.grpc.KnownLength;
import io.grpc.MethodDescriptor;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import javax.annotation.Nullable;
public class FlatbuffersUtils {
abstract public static class FBExtactor <T extends Table> {
public abstract static class FBExtactor<T extends Table> {
T extract(InputStream stream) throws IOException {
if (stream instanceof KnownLength) {
int size = stream.available();
@@ -36,11 +35,13 @@ public class FlatbuffersUtils {
stream.read(buffer.array());
return extract(buffer);
} else
throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength ");
throw new RuntimeException(
"The class "
+ stream.getClass().getCanonicalName()
+ " does not extend from KnownLength ");
}
public abstract T extract(ByteBuffer buffer);
}
static class FBInputStream extends InputStream implements Drainable, KnownLength {
@@ -81,18 +82,17 @@ public class FlatbuffersUtils {
makeStreamIfNotAlready();
return inputStream.read(b, off, len);
}
} else
return inputStream.read(b, off, len);
} else return inputStream.read(b, off, len);
}
@Override
public int available() throws IOException {
return inputStream == null ? size : inputStream.available();
}
}
public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(final Class<T> clazz, final FBExtactor<T> extractor) {
public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(
final Class<T> clazz, final FBExtactor<T> extractor) {
return new MethodDescriptor.ReflectableMarshaller<T>() {
@Override
public Class<T> getMessageClass() {

View File

@@ -40,7 +40,9 @@ static grpc::string FilenameIdentifier(const grpc::string &filename) {
}
template <class T, size_t N>
static T *array_end(T (&array)[N]) { return array + N; }
static T* array_end(T (&array)[N]) {
return array + N;
}
static void PrintIncludes(grpc_generator::Printer* printer,
const std::vector<grpc::string>& headers,
@@ -53,13 +55,26 @@ static void PrintIncludes(grpc_generator::Printer *printer,
auto& s = params.grpc_search_path;
if (!s.empty()) {
vars["l"] += s;
if (s[s.size() - 1] != '/') { vars["l"] += '/'; }
if (s[s.size() - 1] != '/') {
vars["l"] += '/';
}
}
for (auto i = headers.begin(); i != headers.end(); i++) {
vars["h"] = *i;
printer->Print(vars, "#include $l$$h$$r$\n");
}
if (params.generate_callback_api) {
// Callback API headers (guarded later by feature macro in emitted code).
static const char* cb_headers[] = {
"grpcpp/impl/codegen/callback_common.h",
"grpcpp/impl/codegen/server_callback_handlers.h",
"grpcpp/support/client_callback.h"};
for (auto& h : cb_headers) {
vars["h"] = h;
printer->Print(vars, "#include $l$$h$$r$\n");
}
}
}
} // namespace
@@ -113,8 +128,7 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/status.h",
"grpcpp/impl/codegen/stub_options.h",
"grpcpp/impl/codegen/sync_stream.h"
};
"grpcpp/impl/codegen/sync_stream.h"};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
printer->Print(vars, "\n");
@@ -138,7 +152,6 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
return output;
}
namespace {
static void PrintHeaderClientMethodInterfaces(
@@ -355,8 +368,6 @@ static void PrintHeaderClientMethodInterfaces(
}
}
static void PrintHeaderClientMethod(grpc_generator::Printer* printer,
const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars,
@@ -377,6 +388,22 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
*vars,
"::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) override;\n");
if ((*vars)["generate_callback_api"] == "1") {
// Native gRPC callback unary wrappers (function callback & reactor
// variants).
printer->Print(*vars,
"// Callback unary (function form). Request/response "
"must outlive callback.\n");
printer->Print(*vars,
"void async_$Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response, "
"std::function<void(::grpc::Status)> on_done);\n");
printer->Print(*vars, "// Callback unary (reactor form).\n");
printer->Print(*vars,
"void async_$Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response, "
"::grpc::ClientUnaryReactor* reactor);\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -407,6 +434,13 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, response));\n");
printer->Outdent();
printer->Print("}\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(*vars, "// Client streaming callback reactor entry.\n");
printer->Print(
*vars,
"void async_$Method$(::grpc::ClientContext* context, $Response$* "
"response, ::grpc::ClientWriteReactor< $Request$ >* reactor);\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -440,6 +474,13 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, request));\n");
printer->Outdent();
printer->Print("}\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(*vars, "// Server streaming callback reactor entry.\n");
printer->Print(*vars,
"void async_$Method$(::grpc::ClientContext* context, "
"const $Request$& request, ::grpc::ClientReadReactor< "
"$Response$ >* reactor);\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -472,6 +513,14 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"$Method$Raw(context));\n");
printer->Outdent();
printer->Print("}\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(*vars,
"// Bidirectional streaming callback reactor entry.\n");
printer->Print(
*vars,
"void async_$Method$(::grpc::ClientContext* context, "
"::grpc::ClientBidiReactor< $Request$, $Response$ >* reactor);\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -506,6 +555,10 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"const $Request$& request, "
"::grpc::CompletionQueue* cq) override;\n");
}
if ((*vars)["generate_callback_api"] == "1") {
// Native callback unary forms declared earlier (no private sync helper
// needed).
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* $Method$Raw("
@@ -560,16 +613,16 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
}
}
static void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
static void PrintHeaderClientMethodData(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
(*vars)["Method"] = method->name();
printer->Print(*vars,
"const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
}
static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
static void PrintHeaderServerMethodSync(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -602,8 +655,8 @@ static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
printer->Print(method->GetTrailingComments("//").c_str());
}
static void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
static void PrintHeaderServerMethodAsync(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -930,6 +983,10 @@ static void PrintHeaderService(grpc_generator::Printer *printer,
false);
}
printer->Outdent();
// Forward declaration of nested CallbackService if callback API enabled.
if ((*vars)["generate_callback_api"] == "1") {
printer->Print("class CallbackService;\n");
}
printer->Print("};\n");
printer->Print(
"class Stub final : public StubInterface"
@@ -986,7 +1043,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print(*vars, "WithAsyncMethod_$method_name$<");
}
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
for (int i = 0; i < service->method_count(); ++i) {
printer->Print(" >");
}
printer->Print(" AsyncService;\n");
// Server side - Generic
@@ -1011,7 +1070,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer,
}
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
if (service->method(i)->NoStreaming()) {
printer->Print(" >");
}
}
printer->Print(" StreamedUnaryService;\n");
@@ -1033,7 +1094,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
if (ServerOnlyStreaming(method.get())) {
printer->Print(" >");
}
}
printer->Print(" SplitStreamedService;\n");
@@ -1062,6 +1125,48 @@ static void PrintHeaderService(grpc_generator::Printer *printer,
printer->Outdent();
printer->Print("};\n");
printer->Print(service->GetTrailingComments("//").c_str());
// Optional CallbackService (modern async API)
if ((*vars)["generate_callback_api"] == "1") {
(*vars)["Service"] = service->name();
printer->Print("\n#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)\n");
printer->Print(*vars,
"class $Service$::CallbackService : public ::grpc::Service "
"{\n public:\n CallbackService();\n virtual "
"~CallbackService();\n");
printer->Indent();
for (int i = 0; i < service->method_count(); ++i) {
auto m = service->method(i);
(*vars)["Method"] = m->name();
(*vars)["Request"] = m->input_type_name();
(*vars)["Response"] = m->output_type_name();
if (m->NoStreaming()) {
printer->Print(*vars,
"virtual ::grpc::ServerUnaryReactor* "
"$Method$(::grpc::CallbackServerContext* context, const "
"$Request$* request, $Response$* response);\n");
} else if (ClientOnlyStreaming(m.get())) {
printer->Print(*vars,
"virtual ::grpc::ServerReadReactor<$Request$>* "
"$Method$(::grpc::CallbackServerContext* context, "
"$Response$* response);\n");
} else if (ServerOnlyStreaming(m.get())) {
printer->Print(*vars,
"virtual ::grpc::ServerWriteReactor<$Response$>* "
"$Method$(::grpc::CallbackServerContext* context, const "
"$Request$* request);\n");
} else if (m->BidiStreaming()) {
printer->Print(
*vars,
"virtual ::grpc::ServerBidiReactor<$Request$, $Response$>* "
"$Method$(::grpc::CallbackServerContext* context);\n");
}
}
printer->Outdent();
printer->Print(
"};\n#else\n// Callback API requested but not available in this gRPC "
"version.\n#endif // GRPC_CALLBACK_API_NONEXPERIMENTAL\n");
}
}
} // namespace
@@ -1076,7 +1181,9 @@ grpc::string GetHeaderServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) { vars["Package"].append("."); }
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;
@@ -1084,9 +1191,14 @@ grpc::string GetHeaderServices(grpc_generator::File *file,
}
for (int i = 0; i < file->service_count(); ++i) {
vars["generate_callback_api"] = params.generate_callback_api ? "1" : "0";
PrintHeaderService(printer.get(), file->service(i).get(), &vars);
printer->Print("\n");
}
if (params.generate_callback_api) {
printer->Print("// FlatBuffers: Callback API code generated.\n");
printer->Print("#define FLATBUFFERS_GENERATED_GRPC_CALLBACK_API 1\n\n");
}
if (!params.services_namespace.empty()) {
printer->Print(vars, "} // namespace $services_namespace$\n\n");
@@ -1139,7 +1251,8 @@ grpc::string GetSourcePrologue(grpc_generator::File *file,
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars,
"// If you make any local change, they will be lost.\n");
"// FlatBuffers modified generator: native gRPC callback "
"client API enabled when --grpc-callback-api.\n");
printer->Print(vars, "// source: $filename$\n\n");
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
@@ -1165,8 +1278,7 @@ grpc::string GetSourceIncludes(grpc_generator::File *file,
"grpcpp/impl/codegen/method_handler.h",
"grpcpp/impl/codegen/rpc_service_method.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/sync_stream.h"
};
"grpcpp/impl/codegen/sync_stream.h"};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
@@ -1184,11 +1296,10 @@ grpc::string GetSourceIncludes(grpc_generator::File *file,
return output;
}
namespace {
static void PrintSourceClientMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
static void PrintSourceClientMethod(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -1209,6 +1320,28 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer,
" return ::grpc::internal::BlockingUnaryCall"
"(channel_.get(), rpcmethod_$Method$_, "
"context, request, response);\n}\n\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(
*vars,
"void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* "
"context, const $Request$& request, $Response$* response, "
"std::function<void(::grpc::Status)> on_done) {\n");
printer->Print(*vars,
" ::grpc::internal::CallbackUnaryCall(channel_.get(), "
"rpcmethod_$Method$_, context, &request, response, "
"std::move(on_done));\n}\n\n");
printer->Print(
*vars,
"void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* "
"context, const $Request$& request, $Response$* response, "
"::grpc::ClientUnaryReactor* reactor) {\n");
printer->Print(
*vars,
" "
"::grpc::internal::ClientCallbackUnaryFactory::Create(channel_.get(),"
" rpcmethod_$Method$_, context, &request, response, "
"reactor);\n}\n\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -1241,6 +1374,17 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(
*vars,
"void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* "
"context, $Response$* response, ::grpc::ClientWriteReactor< "
"$Request$ >* reactor) {\n");
printer->Print(*vars,
" ::grpc::internal::ClientCallbackWriterFactory< "
"$Request$ >::Create(channel_.get(), rpcmethod_$Method$_, "
"context, response, reactor);\n}\n\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -1274,6 +1418,18 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(
*vars,
"void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* "
"context, const $Request$& request, ::grpc::ClientReadReactor< "
"$Response$ >* reactor) {\n");
printer->Print(
*vars,
" ::grpc::internal::ClientCallbackReaderFactory< "
"$Response$ >::Create(channel_.get(), "
"rpcmethod_$Method$_, context, &request, reactor);\n}\n\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -1307,6 +1463,17 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context);\n"
"}\n\n");
if ((*vars)["generate_callback_api"] == "1") {
printer->Print(
*vars,
"void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* "
"context, ::grpc::ClientBidiReactor< $Request$, $Response$ >* "
"reactor) {\n");
printer->Print(*vars,
" ::grpc::internal::ClientCallbackReaderWriterFactory< "
"$Request$, $Response$ >::Create(channel_.get(), "
"rpcmethod_$Method$_, context, reactor);\n}\n\n");
}
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto& async_prefix = async_prefixes[i];
@@ -1331,8 +1498,8 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer,
}
}
static void PrintSourceServerMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
static void PrintSourceServerMethod(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -1495,6 +1662,114 @@ static void PrintSourceService(grpc_generator::Printer *printer,
(*vars)["Idx"] = as_string(i);
PrintSourceServerMethod(printer, service->method(i).get(), vars);
}
// CallbackService implementation (if enabled)
if ((*vars)["generate_callback_api"] == "1") {
(*vars)["Service"] = service->name();
printer->Print("#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)\n");
printer->Print(*vars,
"$ns$$Service$::CallbackService::CallbackService() {\n");
printer->Indent();
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
(*vars)["Idx"] = as_string(i);
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
if (method->NoStreaming()) {
printer->Print(
*vars,
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
" new ::grpc::internal::CallbackUnaryHandler<$Request$, "
"$Response$>(\n"
" [this](::grpc::CallbackServerContext* ctx, const $Request$* "
"req, $Response$* resp) {\n"
" return this->$Method$(ctx, req, resp);\n"
" })));\n");
} else if (ClientOnlyStreaming(method.get())) {
printer->Print(*vars,
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
" new "
"::grpc::internal::CallbackClientStreamingHandler<$"
"Request$, $Response$>(\n"
" [this](::grpc::CallbackServerContext* ctx, "
"$Response$* resp) {\n"
" return this->$Method$(ctx, resp);\n"
" })));\n");
} else if (ServerOnlyStreaming(method.get())) {
printer->Print(*vars,
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
" new "
"::grpc::internal::CallbackServerStreamingHandler<$"
"Request$, $Response$>(\n"
" [this](::grpc::CallbackServerContext* ctx, const "
"$Request$* req) {\n"
" return this->$Method$(ctx, req);\n"
" })));\n");
} else if (method->BidiStreaming()) {
printer->Print(
*vars,
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
" new ::grpc::internal::CallbackBidiHandler<$Request$, "
"$Response$>(\n"
" [this](::grpc::CallbackServerContext* ctx) {\n"
" return this->$Method$(ctx);\n"
" })));\n");
}
}
printer->Outdent();
printer->Print("}\n\n");
printer->Print(*vars,
"$ns$$Service$::CallbackService::~CallbackService() {}\n\n");
// Default method bodies returning UNIMPLEMENTED reactors.
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::ServerUnaryReactor* "
"$ns$$Service$::CallbackService::$Method$(::grpc::"
"CallbackServerContext* /*context*/, const $Request$* "
"/*request*/, $Response$* /*response*/) {\n"
" return nullptr; // user must override\n"
"}\n\n");
} else if (ClientOnlyStreaming(method.get())) {
printer->Print(
*vars,
"::grpc::ServerReadReactor<$Request$>* "
"$ns$$Service$::CallbackService::$Method$(::grpc::"
"CallbackServerContext* /*context*/, $Response$* /*response*/) {\n"
" return nullptr; // user must override\n"
"}\n\n");
} else if (ServerOnlyStreaming(method.get())) {
printer->Print(*vars,
"::grpc::ServerWriteReactor<$Response$>* "
"$ns$$Service$::CallbackService::$Method$(::grpc::"
"CallbackServerContext* /*context*/, const $Request$* "
"/*request*/) {\n"
" return nullptr; // user must override\n"
"}\n\n");
} else if (method->BidiStreaming()) {
printer->Print(*vars,
"::grpc::ServerBidiReactor<$Request$, $Response$>* "
"$ns$$Service$::CallbackService::$Method$(::grpc::"
"CallbackServerContext* /*context*/) {\n"
" return nullptr; // user must override\n"
"}\n\n");
}
}
printer->Print("#endif // GRPC_CALLBACK_API_NONEXPERIMENTAL\n");
}
}
} // namespace
@@ -1509,7 +1784,9 @@ grpc::string GetSourceServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) { vars["Package"].append("."); }
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!params.services_namespace.empty()) {
vars["ns"] = params.services_namespace + "::";
vars["prefix"] = params.services_namespace;
@@ -1519,6 +1796,7 @@ grpc::string GetSourceServices(grpc_generator::File *file,
}
for (int i = 0; i < file->service_count(); ++i) {
vars["generate_callback_api"] = params.generate_callback_api ? "1" : "0";
PrintSourceService(printer.get(), file->service(i).get(), &vars);
printer->Print("\n");
}
@@ -1601,7 +1879,6 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
return output;
}
namespace {
static void PrintMockClientMethods(grpc_generator::Printer* printer,
@@ -1615,8 +1892,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer,
grpc::string prefix;
grpc::string method_params; // extra arguments to method
int extra_method_param_count;
} async_prefixes[] = { { "Async", ", void* tag", 1 },
{ "PrepareAsync", "", 0 } };
} async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
if (method->NoStreaming()) {
printer->Print(
@@ -1724,7 +2000,9 @@ grpc::string GetMockServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) { vars["Package"].append("."); }
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;

View File

@@ -37,6 +37,8 @@ struct Parameters {
std::string message_header_extension;
// Default: ".grpc.fb.h"
std::string service_header_extension;
// Generate modern callback-based async API service code (CallbackService)
bool generate_callback_api = false;
};
// Return the prologue of the generated header file.

View File

@@ -4,7 +4,8 @@
#include <map>
#include <sstream>
template<class T> grpc::string as_string(T x) {
template <class T>
grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
@@ -67,8 +68,8 @@ static void GenerateImports(grpc_generator::File *file,
}
// Generates Server method signature source
static void GenerateServerMethodSignature(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
static void GenerateServerMethodSignature(
const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
@@ -160,8 +161,12 @@ static void GenerateServerMethod(const grpc_generator::Method *method,
printer->Print(vars, "type $Service$_$Method$Server interface {\n");
printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Response$) error\n"); }
if (genRecv) { printer->Print(vars, "Recv() (*$Request$, error)\n"); }
if (genSend) {
printer->Print(vars, "Send(*$Response$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Request$, error)\n");
}
if (genSendAndClose) {
printer->Print(vars, "SendAndClose(*$Response$) error\n");
}
@@ -205,8 +210,8 @@ static void GenerateServerMethod(const grpc_generator::Method *method,
}
// Generates Client method signature source
static void GenerateClientMethodSignature(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
static void GenerateClientMethodSignature(
const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] =
@@ -277,8 +282,12 @@ static void GenerateClientMethod(const grpc_generator::Method *method,
// Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Request$) error\n"); }
if (genRecv) { printer->Print(vars, "Recv() (*$Response$, error)\n"); }
if (genSend) {
printer->Print(vars, "Send(*$Request$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Response$, error)\n");
}
if (genCloseAndRecv) {
printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
}

View File

@@ -136,8 +136,7 @@ static void GrpcSplitStringToIteratorUsing(const string &full,
++p;
} else {
const char* start = p;
while (++p != end && *p != c)
;
while (++p != end && *p != c);
*result++ = string(start, p - start);
}
}
@@ -218,7 +217,9 @@ static string GrpcEscapeJavadoc(const string &input) {
// Java interprets Unicode escape sequences anywhere!
result.append("&#92;");
break;
default: result.push_back(c); break;
default:
result.push_back(c);
break;
}
prev = c;
@@ -238,7 +239,9 @@ static std::vector<string> GrpcGetDocLines(const string &comments) {
string escapedComments = GrpcEscapeJavadoc(comments);
std::vector<string> lines = GrpcSplit(escapedComments, "\n");
while (!lines.empty() && lines.back().empty()) { lines.pop_back(); }
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
return lines;
}
return std::vector<string>();
@@ -254,7 +257,9 @@ static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
const std::vector<string>& lines,
bool surroundWithPreTag) {
if (!lines.empty()) {
if (surroundWithPreTag) { printer->Print(" * <pre>\n"); }
if (surroundWithPreTag) {
printer->Print(" * <pre>\n");
}
for (size_t i = 0; i < lines.size(); i++) {
// Most lines should start with a space. Watch out for lines that start
@@ -268,7 +273,9 @@ static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
}
}
if (surroundWithPreTag) { printer->Print(" * </pre>\n"); }
if (surroundWithPreTag) {
printer->Print(" * </pre>\n");
}
}
}
@@ -493,7 +500,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
vars["client_name"] = client_name;
// Class head
if (!interface) { GrpcWriteServiceDocComment(p, vars, service); }
if (!interface) {
GrpcWriteServiceDocComment(p, vars, service);
}
if (impl_base) {
p->Print(vars,
"public static abstract class $abstract_name$ implements "
@@ -555,7 +564,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
p->Print("\n");
// TODO(nmittler): Replace with WriteMethodDocComment once included by the
// protobuf distro.
if (!interface) { GrpcWriteMethodDocComment(p, vars, &*method); }
if (!interface) {
GrpcWriteMethodDocComment(p, vars, &*method);
}
p->Print("public ");
switch (call_type) {
case BLOCKING_CALL:
@@ -620,7 +631,8 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
"responseObserver);\n");
}
break;
default: break;
default:
break;
}
} else if (!interface) {
switch (call_type) {
@@ -746,7 +758,9 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (method->ClientStreaming() || method->BidiStreaming()) { continue; }
if (method->ClientStreaming() || method->BidiStreaming()) {
continue;
}
vars["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
@@ -778,7 +792,9 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (!(method->ClientStreaming() || method->BidiStreaming())) { continue; }
if (!(method->ClientStreaming() || method->BidiStreaming())) {
continue;
}
vars["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());

View File

@@ -18,6 +18,7 @@
#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_
#include <stdlib.h> // for abort()
#include <iostream>
#include <map>
#include <string>
@@ -39,8 +40,8 @@ class LogHelper {
LogHelper(std::ostream* os) : os_(os) {}
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning( \
disable : 4722) // the flow of control terminates in a destructor
#pragma warning(disable \
: 4722) // the flow of control terminates in a destructor
// (needed to compile ~LogHelper where destructor emits abort intentionally -
// inherited from grpc/java code generator).
#endif

View File

@@ -37,12 +37,14 @@ namespace grpc {
namespace {
bool ClientStreaming(const RPCCall* method) {
const Value* val = method->attributes.Lookup("streaming");
return val != nullptr && (val->constant == "client" || val->constant == "bidi");
return val != nullptr &&
(val->constant == "client" || val->constant == "bidi");
}
bool ServerStreaming(const RPCCall* method) {
const Value* val = method->attributes.Lookup("streaming");
return val != nullptr && (val->constant == "server" || val->constant == "bidi");
return val != nullptr &&
(val->constant == "server" || val->constant == "bidi");
}
void FormatImports(std::stringstream& ss, const Imports& imports) {
@@ -105,7 +107,8 @@ class BaseGenerator {
const std::string& path, const Version& version)
: parser_{parser},
namer_{WithFlagOptions(config, parser.opts, path), Keywords(version)},
version_{version} {}
version_{version},
path_(path) {}
protected:
std::string ModuleForFile(const std::string& file) const {
@@ -121,9 +124,29 @@ class BaseGenerator {
return namer_.NamespacedType(*def);
}
std::string NamespaceDir(const Parser& parser, const std::string& path,
const Namespace& ns, const bool dasherize) {
EnsureDirExists(path);
if (parser.opts.one_file) return path;
std::string namespace_dir = path; // Either empty or ends in separator.
auto& namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
namespace_dir +=
!dasherize ? *it : ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
namespace_dir += kPathSeparator;
EnsureDirExists(namespace_dir);
}
return namespace_dir;
}
std::string NamespaceDir(const Namespace& ns, const bool dasherize) {
return NamespaceDir(parser_, path_, ns, dasherize);
}
const Parser& parser_;
const IdlNamer namer_;
const Version version_;
const std::string& path_;
};
class StubGenerator : public BaseGenerator {
@@ -135,14 +158,18 @@ class StubGenerator : public BaseGenerator {
bool Generate() {
Imports imports;
std::stringstream stub;
std::string ns_name{};
for (const ServiceDef* service : parser_.services_.vec) {
Generate(stub, service, &imports);
ns_name = NamespaceDir(*service->defined_namespace, false);
}
std::string sanitized_suffix{parser_.opts.grpc_filename_suffix};
std::replace(sanitized_suffix.begin(), sanitized_suffix.end(), '.', '_');
std::string filename =
namer_.config_.output_path +
ns_name + kPathSeparator +
StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" +
parser_.opts.grpc_filename_suffix + namer_.config_.filename_extension;
sanitized_suffix + namer_.config_.filename_extension;
return SaveStub(filename, imports, stub.str());
}
@@ -247,16 +274,20 @@ class ServiceGenerator : public BaseGenerator {
<< '\n';
}
std::string ns_name{};
for (const ServiceDef* service : parser_.services_.vec) {
GenerateStub(ss, service, &imports);
GenerateServicer(ss, service, &imports);
GenerateRegister(ss, service, &imports);
ns_name = NamespaceDir(*service->defined_namespace, false);
}
std::string sanitized_suffix{parser_.opts.grpc_filename_suffix};
std::replace(sanitized_suffix.begin(), sanitized_suffix.end(), '.', '_');
std::string filename =
namer_.config_.output_path +
ns_name + kPathSeparator +
StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" +
parser_.opts.grpc_filename_suffix + namer_.config_.filename_extension;
sanitized_suffix + namer_.config_.filename_extension;
return SaveService(filename, imports, ss.str());
}

View File

@@ -20,12 +20,13 @@
* please open an issue in the flatbuffers repository. This file should always
* be maintained according to the Swift-grpc repository
*/
#include "src/compiler/swift_generator.h"
#include <map>
#include <sstream>
#include "flatbuffers/util.h"
#include "src/compiler/schema_interface.h"
#include "src/compiler/swift_generator.h"
namespace grpc_swift_generator {
namespace {
@@ -45,8 +46,8 @@ static grpc::string GenerateMessage(const std::vector<std::string> &components,
// MARK: - Client
static void GenerateClientFuncName(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
static void GenerateClientFuncName(
const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
if (method->NoStreaming()) {
@@ -83,8 +84,8 @@ static void GenerateClientFuncName(const grpc_generator::Method *method,
" ) -> BidirectionalStreamingCall<$Input$, $Output$>");
}
static void GenerateClientFuncBody(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
static void GenerateClientFuncBody(
const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
vars["Interceptor"] =
@@ -380,7 +381,9 @@ grpc::string Generate(grpc_generator::File *file,
grpc::string output;
std::map<grpc::string, grpc::string> vars;
vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); }
if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceQualifiedName"] =
WrapInNameSpace(service->namespace_parts(), service->name());
vars["ServiceName"] = service->name();
@@ -394,6 +397,8 @@ grpc::string Generate(grpc_generator::File *file,
GenerateClientClass(&*printer, &vars);
printer->Print("\n");
GenerateServerProtocol(service, &*printer, &vars);
printer->Print("\n");
printer->Print("#endif\n");
return output;
}
@@ -409,6 +414,7 @@ grpc::string GenerateHeader() {
code += "// swiftlint:disable all\n";
code += "// swiftformat:disable all\n";
code += "\n";
code += "#if !os(Windows)\n";
code += "import Foundation\n";
code += "import GRPC\n";
code += "import NIO\n";
@@ -428,10 +434,7 @@ grpc::string GenerateHeader() {
code += " }\n";
code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
code +=
" let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
"Int(self.size))\n";
code += " buffer.writeBytes(buf)\n";
code += " withUnsafeReadableBytes { buffer.writeBytes($0) }\n";
code += " }\n";
code += "}\n";
code += "extension Message: GRPCFlatBufPayload {}\n";

View File

@@ -117,7 +117,8 @@ static void GetStreamType(grpc_generator::Printer *printer,
printer->Print(vars, "responseStream: $ServerStreaming$,\n");
}
static void GenerateSerializeMethod(grpc_generator::Printer *printer,
static void GenerateSerializeMethod(
grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
printer->Print(vars, "function serialize_$Type$(buffer_args) {\n");
@@ -223,7 +224,9 @@ grpc::string Generate(grpc_generator::File *file,
vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); }
if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceName"] = service->name();
vars["FBSFile"] = service->name() + "_fbs";
@@ -258,8 +261,8 @@ static void FillInterface(grpc_generator::Printer *printer,
printer->Print("}\n");
}
static void GenerateInterfaces(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
static void GenerateInterfaces(
const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
for (auto it = 0; it < service->method_count(); it++) {
@@ -324,8 +327,8 @@ static void GenerateExportedInterface(
printer->Print("}\n");
}
static void GenerateMainInterface(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
static void GenerateMainInterface(
const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
printer->Print(
@@ -351,7 +354,9 @@ static void GenerateMainInterface(const grpc_generator::Service *service,
static grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; }
static grpc::string GenerateOptions() { return "options: Partial<grpc.CallOptions>"; }
static grpc::string GenerateOptions() {
return "options: Partial<grpc.CallOptions>";
}
static void GenerateUnaryClientInterface(
grpc_generator::Printer* printer,
@@ -413,8 +418,8 @@ static void GenerateDepluxStreamInterface(
.c_str());
}
static void GenerateClientInterface(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
static void GenerateClientInterface(
const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary;
printer->Print(vars, "export interface I$ServiceName$Client {\n");
@@ -494,7 +499,6 @@ static void GenerateClientClassInterface(
}
} // namespace
grpc::string GenerateInterface(grpc_generator::File* file,
const grpc_generator::Service* service,
const grpc::string& filename) {
@@ -505,7 +509,9 @@ grpc::string GenerateInterface(grpc_generator::File *file,
vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); }
if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceName"] = service->name();
vars["FBSFile"] = service->name() + "_fbs";

View File

@@ -17,3 +17,27 @@ cc_test(
"@com_github_grpc_grpc//:grpc++",
],
)
cc_test(
name = "grpc_callback_compile_test",
srcs = ["grpctest_callback_compile.cpp"],
copts = ["-Itests"],
linkstatic = 1,
deps = [
"//tests:monster_test_cc_fbs",
"//tests:monster_test_grpc",
"@com_github_grpc_grpc//:grpc++",
],
)
cc_test(
name = "grpc_callback_client_compile_test",
srcs = ["grpctest_callback_client_compile.cpp"],
copts = ["-Itests"],
linkstatic = 1,
deps = [
"//tests:monster_test_cc_fbs",
"//tests:monster_test_grpc",
"@com_github_grpc_grpc//:grpc++",
],
)

View File

@@ -1,10 +1,11 @@
import java.nio.ByteBuffer;
import MyGame.Example.Monster;
import MyGame.Example.Stat;
import com.google.flatbuffers.FlatBufferBuilder;
import java.nio.ByteBuffer;
class GameFactory {
public static Monster createMonster(String monsterName, short nestedMonsterHp, short nestedMonsterMana) {
public static Monster createMonster(
String monsterName, short nestedMonsterHp, short nestedMonsterMana) {
FlatBufferBuilder builder = new FlatBufferBuilder();
int name_offset = builder.createString(monsterName);
@@ -38,5 +39,4 @@ class GameFactory {
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
return stat;
}
}

View File

@@ -17,27 +17,20 @@
import MyGame.Example.Monster;
import MyGame.Example.MonsterStorageGrpc;
import MyGame.Example.Stat;
import com.google.flatbuffers.FlatBufferBuilder;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Assert;
import java.io.IOException;
import java.lang.InterruptedException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
/**
* Demonstrates basic client-server interaction using grpc-java over netty.
*/
/** Demonstrates basic client-server interaction using grpc-java over netty. */
public class JavaGrpcTest {
static final String BIG_MONSTER_NAME = "Cyberdemon";
static final short nestedMonsterHp = 600;
@@ -82,7 +75,8 @@ public class JavaGrpcTest {
return computeMinMax(responseObserver, true);
}
private StreamObserver<Monster> computeMinMax(final StreamObserver<Stat> responseObserver, final boolean includeMin) {
private StreamObserver<Monster> computeMinMax(
final StreamObserver<Stat> responseObserver, final boolean includeMin) {
final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE);
final AtomicReference<String> maxHpMonsterName = new AtomicReference<String>();
final AtomicInteger maxHpCount = new AtomicInteger();
@@ -98,8 +92,7 @@ public class JavaGrpcTest {
maxHp.set(monster.hp());
maxHpMonsterName.set(monster.name());
maxHpCount.set(1);
}
else if (monster.hp() == maxHp.get()) {
} else if (monster.hp() == maxHp.get()) {
// Count how many times we saw a monster of current max hit points.
maxHpCount.getAndIncrement();
}
@@ -109,27 +102,31 @@ public class JavaGrpcTest {
minHp.set(monster.hp());
minHpMonsterName.set(monster.name());
minHpCount.set(1);
}
else if (monster.hp() == minHp.get()) {
} else if (monster.hp() == minHp.get()) {
// Count how many times we saw a monster of current min hit points.
minHpCount.getAndIncrement();
}
}
public void onCompleted() {
Stat maxHpStat = GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get());
Stat maxHpStat =
GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get());
// Send max hit points first.
responseObserver.onNext(maxHpStat);
if (includeMin) {
// Send min hit points.
Stat minHpStat = GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get());
Stat minHpStat =
GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get());
responseObserver.onNext(minHpStat);
}
responseObserver.onCompleted();
}
public void onError(Throwable t) {
// Not expected
Assert.fail();
};
}
;
};
}
}
@@ -138,7 +135,8 @@ public class JavaGrpcTest {
public static void startServer() throws IOException {
server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
int port = server.getPort();
channel = ManagedChannelBuilder.forAddress("localhost", port)
channel =
ManagedChannelBuilder.forAddress("localhost", port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
@@ -150,7 +148,8 @@ public class JavaGrpcTest {
@org.junit.Test
public void testUnary() throws IOException {
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
Monster monsterRequest =
GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
Stat stat = blockingStub.store(monsterRequest);
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
System.out.println("Received stat response from service: " + stat.id());
@@ -158,7 +157,8 @@ public class JavaGrpcTest {
@org.junit.Test
public void testServerStreaming() throws IOException {
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
Monster monsterRequest =
GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
Stat stat = blockingStub.store(monsterRequest);
Iterator<Monster> iterator = blockingStub.retrieve(stat);
int counter = 0;
@@ -176,11 +176,14 @@ public class JavaGrpcTest {
final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
final CountDownLatch streamAlive = new CountDownLatch(1);
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
StreamObserver<Stat> statObserver =
new StreamObserver<Stat>() {
public void onCompleted() {
streamAlive.countDown();
}
public void onError(Throwable ex) {}
public void onNext(Stat stat) {
maxHitStat.set(stat);
}
@@ -188,7 +191,9 @@ public class JavaGrpcTest {
StreamObserver<Monster> monsterStream = asyncStub.getMaxHitPoint(statObserver);
short count = 10;
for (short i = 0; i < count; ++i) {
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
Monster monster =
GameFactory.createMonster(
BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
monsterStream.onNext(monster);
}
monsterStream.onCompleted();
@@ -205,17 +210,19 @@ public class JavaGrpcTest {
final AtomicReference<Stat> minHitStat = new AtomicReference<Stat>();
final CountDownLatch streamAlive = new CountDownLatch(1);
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
StreamObserver<Stat> statObserver =
new StreamObserver<Stat>() {
public void onCompleted() {
streamAlive.countDown();
}
public void onError(Throwable ex) {}
public void onNext(Stat stat) {
// We expect the server to send the max stat first and then the min stat.
if (maxHitStat.get() == null) {
maxHitStat.set(stat);
}
else {
} else {
minHitStat.set(stat);
}
}
@@ -223,12 +230,15 @@ public class JavaGrpcTest {
StreamObserver<Monster> monsterStream = asyncStub.getMinMaxHitPoints(statObserver);
short count = 10;
for (short i = 0; i < count; ++i) {
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
Monster monster =
GameFactory.createMonster(
BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
monsterStream.onNext(monster);
}
monsterStream.onCompleted();
// Wait a little bit for the server to send the stats of the monster with the max and min hit-points.
// Wait a little bit for the server to send the stats of the monster with the max and min
// hit-points.
streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));

View File

@@ -98,7 +98,8 @@ void RunServer() {
server_instance->Wait();
}
template<class Builder> void StoreRPC(MonsterStorage::Stub *stub) {
template <class Builder>
void StoreRPC(MonsterStorage::Stub* stub) {
Builder fbb;
grpc::ClientContext context;
// Build a request with the name set.
@@ -119,7 +120,8 @@ template<class Builder> void StoreRPC(MonsterStorage::Stub *stub) {
}
}
template<class Builder> void RetrieveRPC(MonsterStorage::Stub *stub) {
template <class Builder>
void RetrieveRPC(MonsterStorage::Stub* stub) {
Builder fbb;
grpc::ClientContext context;
fbb.Clear();

View File

@@ -1,13 +1,13 @@
from __future__ import print_function
from concurrent import futures
import os
import sys
import grpc
import flatbuffers
import grpc
from concurrent import futures
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests'))
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "tests"))
import MyGame.Example.Monster as Monster
import MyGame.Example.Stat as Stat
import MyGame.Example.Vec3 as Vec3
@@ -103,7 +103,7 @@ def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server)
server.add_insecure_port('[::]:50051')
server.add_insecure_port("[::]:50051")
server.start()
@@ -112,7 +112,7 @@ def serve():
def run():
channel = grpc.insecure_channel('127.0.0.1:50051')
channel = grpc.insecure_channel("127.0.0.1:50051")
stub = monster_grpc_fb.MonsterStorageStub(channel)
b = flatbuffers.Builder(0)
@@ -142,7 +142,9 @@ def run():
Monster.MonsterAddHp(b, test_hp)
Monster.MonsterAddName(b, name1)
Monster.MonsterAddColor(b, test_color)
pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b)
pos = Vec3.CreateVec3(
b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b
)
Monster.MonsterAddPos(b, pos)
Monster.MonsterAddInventory(b, inv)
Monster.MonsterAddTestType(b, test_testtype)
@@ -170,5 +172,5 @@ def run():
count = count + 1
if __name__ == '__main__':
if __name__ == "__main__":
serve()

View File

@@ -0,0 +1,60 @@
// Verifies that the generated gRPC callback client stub methods are present.
// This is a compile-time only test: it never performs an actual RPC.
// It supplements grpctest_callback_compile.cpp (server side) by checking
// client-side async_ / reactor entry points.
#include <type_traits>
#include "monster_test.grpc.fb.h"
#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \
defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)
using Stub = MyGame::Example::MonsterStorage::Stub;
using namespace MyGame::Example; // NOLINT
// Unary async overloads
static_assert(std::is_member_function_pointer<
decltype(static_cast<void (Stub::*)(
::grpc::ClientContext*,
const flatbuffers::grpc::Message<Monster>&,
flatbuffers::grpc::Message<Stat>*,
std::function<void(::grpc::Status)>)>(
&Stub::async_Store))>::value,
"Function-form unary async_Store missing");
static_assert(
std::is_member_function_pointer<
decltype(static_cast<void (Stub::*)(
::grpc::ClientContext*,
const flatbuffers::grpc::Message<Monster>&,
flatbuffers::grpc::Message<Stat>*,
::grpc::ClientUnaryReactor*)>(&Stub::async_Store))>::value,
"Reactor-form unary async_Store missing");
// Streaming reactor entry points
static_assert(
std::is_member_function_pointer<
decltype(static_cast<void (Stub::*)(
::grpc::ClientContext*,
const flatbuffers::grpc::Message<Stat>&,
::grpc::ClientReadReactor<flatbuffers::grpc::Message<
Monster> >*)>(&Stub::async_Retrieve))>::value,
"Server streaming reactor async_Retrieve missing");
static_assert(
std::is_member_function_pointer<
decltype(static_cast<void (Stub::*)(
::grpc::ClientContext*, flatbuffers::grpc::Message<Stat>*,
::grpc::ClientWriteReactor<flatbuffers::grpc::Message<
Monster> >*)>(&Stub::async_GetMaxHitPoint))>::value,
"Client streaming reactor async_GetMaxHitPoint missing");
static_assert(std::is_member_function_pointer<
decltype(static_cast<void (Stub::*)(
::grpc::ClientContext*,
::grpc::ClientBidiReactor<
flatbuffers::grpc::Message<Monster>,
flatbuffers::grpc::Message<Stat> >*)>(
&Stub::async_GetMinMaxHitPoints))>::value,
"Bidi streaming reactor async_GetMinMaxHitPoints missing");
#endif // FLATBUFFERS_GENERATED_GRPC_CALLBACK_API &&
// GRPC_CALLBACK_API_NONEXPERIMENTAL
int main() { return 0; }

View File

@@ -0,0 +1,22 @@
#include "monster_test.grpc.fb.h"
// This test only verifies that the generated CallbackService compiles when the
// callback API is available. It does not run any RPCs.
#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \
defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)
class CallbackServiceImpl
: public MyGame::Example::MonsterStorage::CallbackService {
public:
// For brevity we don't override methods; user code will provide reactors.
};
#endif
int main() {
#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \
defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)
CallbackServiceImpl svc;
(void)svc; // suppress unused
#endif
return 0;
}

View File

@@ -45,7 +45,9 @@ template<class SrcBuilder>
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
static void builder_reusable_after_release_message_test(
TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; }
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
return;
}
flatbuffers::grpc::MessageBuilder mb;
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
@@ -58,7 +60,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
}
static void builder_reusable_after_release_test(TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
if (!selector.count(REUSABLE_AFTER_RELEASE)) {
return;
}
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
// SliceAllocator::allocate in the second iteration.
@@ -74,7 +78,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
}
static void builder_reusable_after_releaseraw_test(TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) {
return;
}
flatbuffers::grpc::MessageBuilder mb;
for (int i = 0; i < 5; ++i) {
@@ -89,7 +95,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
static void builder_reusable_after_release_and_move_assign_test(
TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) {
return;
}
// FIXME: Release-move_assign loop fails assert(p ==
// GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the
@@ -137,7 +145,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
static void builder_reusable_after_releaseraw_and_move_assign_test(
TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) {
return;
}
flatbuffers::grpc::MessageBuilder dst;
for (int i = 0; i < 5; ++i) {
@@ -358,8 +368,7 @@ void message_builder_tests() {
REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
};
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN};
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
TestSelector(tests, tests + 6));

View File

@@ -104,10 +104,10 @@ class IdlNamer : public Namer {
return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper);
}
std::string LegacyRustUnionTypeOffsetName(const FieldDef& field) const {
return "VT_" + ConvertCase(EscapeKeyword(field.name + "_type"), Case::kAllUpper);
return "VT_" +
ConvertCase(EscapeKeyword(field.name + "_type"), Case::kAllUpper);
}
std::string LegacySwiftVariant(const EnumVal& ev) const {
auto name = ev.name;
if (isupper(name.front())) {
@@ -155,7 +155,9 @@ class IdlNamer : public Namer {
std::string NamespacedString(const struct Namespace* ns,
const std::string& str) const {
std::string ret;
if (ns != nullptr) { ret += Namespace(ns->components); }
if (ns != nullptr) {
ret += Namespace(ns->components);
}
if (!ret.empty()) ret += config_.namespace_seperator;
return ret + str;
}

View File

@@ -110,12 +110,12 @@ class Namer {
virtual ~Namer() {}
template<typename T> std::string Method(const T &s) const {
template <typename T>
std::string Method(const T& s) const {
return Method(s.name);
}
virtual std::string Method(const std::string &pre,
const std::string &mid,
virtual std::string Method(const std::string& pre, const std::string& mid,
const std::string& suf) const {
return Format(pre + "_" + mid + "_" + suf, config_.methods);
}

View File

@@ -59,5 +59,21 @@ const python::Import &python::Imports::Import(const std::string &module,
imports.push_back(std::move(import));
return imports.back();
}
const python::Import& python::Imports::Export(const std::string& module) {
python::Import import;
import.module = module;
exports.push_back(std::move(import));
return exports.back();
}
const python::Import& python::Imports::Export(const std::string& module,
const std::string& name) {
python::Import import;
import.module = module;
import.name = name;
exports.push_back(std::move(import));
return exports.back();
}
} // namespace python
} // namespace flatbuffers

View File

@@ -85,7 +85,12 @@ struct Imports {
const python::Import& Import(const std::string& module,
const std::string& name);
const python::Import& Export(const std::string& module);
const python::Import& Export(const std::string& module,
const std::string& name);
std::vector<python::Import> imports;
std::vector<python::Import> exports;
};
} // namespace python
} // namespace flatbuffers

View File

@@ -27,17 +27,15 @@
namespace flatbuffers {
// This is used as a helper type for accessing arrays.
template<typename T, uint16_t length> class Array {
template <typename T, uint16_t length>
class Array {
// Array<T> can carry only POD data types (scalars or structs).
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
scalar_tag;
typedef
typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
IndirectHelperType;
public:
typedef uint16_t size_type;
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
typedef typename IndirectHelper<T>::return_type return_type;
typedef VectorConstIterator<T, return_type, uoffset_t> const_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
@@ -50,7 +48,7 @@ template<typename T, uint16_t length> class Array {
return_type Get(uoffset_t i) const {
FLATBUFFERS_ASSERT(i < size());
return IndirectHelper<IndirectHelperType>::Read(Data(), i);
return IndirectHelper<T>::Read(Data(), i);
}
return_type operator[](uoffset_t i) const { return Get(i); }
@@ -58,7 +56,8 @@ template<typename T, uint16_t length> class Array {
// If this is a Vector of enums, T will be its storage type, not the enum
// type. This function makes it convenient to retrieve value with enum
// type E.
template<typename E> E GetEnum(uoffset_t i) const {
template <typename E>
E GetEnum(uoffset_t i) const {
return static_cast<E>(Get(i));
}
@@ -134,7 +133,9 @@ template<typename T, uint16_t length> class Array {
// Copy data from flatbuffers::span with endian conversion.
void CopyFromSpanImpl(flatbuffers::false_type,
flatbuffers::span<const T, length> src) {
for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
for (size_type k = 0; k < length; k++) {
Mutate(k, src[k]);
}
}
// This class is only used to access pre-existing data. Don't ever

View File

@@ -140,8 +140,8 @@
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 25
#define FLATBUFFERS_VERSION_MINOR 2
#define FLATBUFFERS_VERSION_REVISION 10
#define FLATBUFFERS_VERSION_MINOR 9
#define FLATBUFFERS_VERSION_REVISION 23
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {

View File

@@ -20,12 +20,14 @@
#include <algorithm>
#include "flatbuffers/base.h"
#include "flatbuffers/stl_emulation.h"
namespace flatbuffers {
// Wrapper for uoffset_t to allow safe template specialization.
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
template<typename T = void> struct Offset {
template <typename T = void>
struct Offset {
// The type of offset to use.
typedef uoffset_t offset_type;
@@ -36,8 +38,14 @@ template<typename T = void> struct Offset {
bool IsNull() const { return !o; }
};
template <typename T>
struct is_specialisation_of_Offset : false_type {};
template <typename T>
struct is_specialisation_of_Offset<Offset<T>> : true_type {};
// Wrapper for uoffset64_t Offsets.
template<typename T = void> struct Offset64 {
template <typename T = void>
struct Offset64 {
// The type of offset to use.
typedef uoffset64_t offset_type;
@@ -48,6 +56,11 @@ template<typename T = void> struct Offset64 {
bool IsNull() const { return !o; }
};
template <typename T>
struct is_specialisation_of_Offset64 : false_type {};
template <typename T>
struct is_specialisation_of_Offset64<Offset64<T>> : true_type {};
// Litmus check for ensuring the Offsets are the expected size.
static_assert(sizeof(Offset<>) == 4, "Offset has wrong size");
static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
@@ -60,7 +73,8 @@ inline void EndianCheck() {
(void)endiantest;
}
template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
template <typename T>
FLATBUFFERS_CONSTEXPR size_t AlignOf() {
// clang-format off
#ifdef _MSC_VER
return __alignof(T);
@@ -90,7 +104,8 @@ static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
// return type like this.
// The typedef is for the convenience of callers of this function
// (avoiding the need for a trailing return decltype)
template<typename T> struct IndirectHelper {
template <typename T, typename Enable = void>
struct IndirectHelper {
typedef T return_type;
typedef T mutable_return_type;
static const size_t element_stride = sizeof(T);
@@ -135,10 +150,20 @@ struct IndirectHelper<OffsetT<T>> {
};
// For vector of structs.
template<typename T> struct IndirectHelper<const T *> {
typedef const T *return_type;
typedef T *mutable_return_type;
static const size_t element_stride = sizeof(T);
template <typename T>
struct IndirectHelper<
T, typename std::enable_if<
!std::is_scalar<typename std::remove_pointer<T>::type>::value &&
!is_specialisation_of_Offset<T>::value &&
!is_specialisation_of_Offset64<T>::value>::type> {
private:
typedef typename std::remove_pointer<typename std::remove_cv<T>::type>::type
pointee_type;
public:
typedef const pointee_type* return_type;
typedef pointee_type* mutable_return_type;
static const size_t element_stride = sizeof(pointee_type);
static return_type Read(const uint8_t* const p, const size_t i) {
// Structs are stored inline, relative to the first struct pointer.
@@ -172,11 +197,11 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier,
/// @cond FLATBUFFERS_INTERNAL
// Helpers to get a typed pointer to the root object contained in the buffer.
template<typename T> T *GetMutableRoot(void *buf) {
template <typename T>
T* GetMutableRoot(void* buf) {
if (!buf) return nullptr;
EndianCheck();
return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(buf) +
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(buf) +
EndianScalar(*reinterpret_cast<uoffset_t*>(buf)));
}
@@ -185,7 +210,8 @@ T *GetMutableSizePrefixedRoot(void *buf) {
return GetMutableRoot<T>(reinterpret_cast<uint8_t*>(buf) + sizeof(SizeT));
}
template<typename T> const T *GetRoot(const void *buf) {
template <typename T>
const T* GetRoot(const void* buf) {
return GetMutableRoot<T>(const_cast<void*>(buf));
}

View File

@@ -27,7 +27,8 @@ namespace flatbuffers {
// A BufferRef does not own its buffer.
struct BufferRefBase {}; // for std::is_base_of
template<typename T> struct BufferRef : BufferRefBase {
template <typename T>
struct BufferRef : BufferRefBase {
BufferRef() : buf(nullptr), len(0), must_free(false) {}
BufferRef(uint8_t* _buf, uoffset_t _len)
: buf(_buf), len(_len), must_free(false) {}

View File

@@ -100,7 +100,9 @@ class DetachedBuffer {
inline void destroy() {
if (buf_) Deallocate(allocator_, buf_, reserved_);
if (own_allocator_ && allocator_) { delete allocator_; }
if (own_allocator_ && allocator_) {
delete allocator_;
}
reset();
}

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