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 Language: Cpp
BasedOnStyle: Google 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: build-cpp-std:
name: Build Windows C++ name: Build Windows C++
runs-on: windows-2019 runs-on: windows-2022
strategy: strategy:
matrix: matrix:
std: [11, 14, 17, 20, 23] std: [11, 14, 17, 20, 23]
@@ -140,7 +140,7 @@ jobs:
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
run: > 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_STRICT_MODE=ON
-DFLATBUFFERS_CPP_STD=${{ matrix.std }} -DFLATBUFFERS_CPP_STD=${{ matrix.std }}
-DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}} -DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}}
@@ -157,14 +157,14 @@ jobs:
contents: write contents: write
outputs: outputs:
digests: ${{ steps.hash.outputs.hashes }} digests: ${{ steps.hash.outputs.hashes }}
name: Build Windows 2019 name: Build Windows 2022
runs-on: windows-2019 runs-on: windows-2022
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
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 - name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: test - name: test
@@ -310,14 +310,17 @@ jobs:
build-android: build-android:
name: Build Android (on Linux) name: Build Android (on Linux)
if: false #disabled due to continual failure
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: set up Java - name: set up Java
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: temurin
java-version: '11' java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: set up flatc - name: set up flatc
run: | run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
@@ -344,13 +347,13 @@ jobs:
build-generator-windows: build-generator-windows:
name: Check Generated Code on Windows name: Check Generated Code on Windows
runs-on: windows-2019 runs-on: windows-2022
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: cmake - name: cmake
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 - name: build
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
- name: Generate - name: Generate
@@ -398,11 +401,13 @@ jobs:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode
- name: Set up Xcode version - name: Set up Xcode version
run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
- uses: gradle/wrapper-validation-action@v1.0.5 - name: set up Java
- uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: temurin
java-version: '11' java-version: 17
- name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build flatc - name: Build flatc
run: | run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -414,15 +419,18 @@ jobs:
build-kotlin-linux: build-kotlin-linux:
name: Build Kotlin Linux name: Build Kotlin Linux
if: false #disabled due to continual failure
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- uses: actions/setup-java@v3 - name: set up Java
uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: temurin
java-version: '11' java-version: 17
- uses: gradle/wrapper-validation-action@v1.0.5 - name: set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build flatc - name: Build flatc
run: | run: |
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
@@ -492,27 +500,37 @@ jobs:
sh phpUnionVectorTest.sh sh phpUnionVectorTest.sh
build-swift: build-swift:
name: Build Swift name: Test Swift
strategy: strategy:
matrix: 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 # 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 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: swift-actions/setup-swift@v2 - uses: vapor/swiftly-action@v0.2
with: with:
swift-version: ${{ matrix.swift }} toolchain: ${{ matrix.swift }}
- name: Get swift version - name: Get swift version
run: swift --version run: swift --version
- name: test - name: test
working-directory: tests/swift/tests
run: | run: |
swift build --build-tests swift build --build-tests
swift test 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: build-swift-wasm:
name: Build Swift Wasm name: Test Swift Wasm
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
container: container:
image: ghcr.io/swiftwasm/carton:0.20.1 image: ghcr.io/swiftwasm/carton:0.20.1
@@ -534,14 +552,15 @@ jobs:
- name: flatc - name: flatc
# FIXME: make test script not rely on flatc # FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm
run: npm install -g pnpm esbuild
- name: deps - name: deps
run: yarn run: pnpm i
- name: compile - name: compile
run: yarn compile run: pnpm compile
- name: test - name: test
working-directory: tests/ts working-directory: tests/ts
run: | run: |
yarn global add esbuild
python3 TypeScriptTest.py python3 TypeScriptTest.py
build-dart: 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 new features that should be highlighted. Minor fixes or improvements are not
necessarily listed. 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) ## [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 * 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_MAJOR 25)
set(VERSION_MINOR 2) set(VERSION_MINOR 9)
set(VERSION_PATCH 10) set(VERSION_PATCH 23)
set(VERSION_COMMIT 0) set(VERSION_COMMIT 0)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")

View File

@@ -112,6 +112,7 @@ endif()
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>) add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
if(NOT WIN32) if(NOT WIN32)
include(CheckSymbolExists)
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH) check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
if(NOT HAVE_REALPATH) if(NOT HAVE_REALPATH)
add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION) add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION)
@@ -278,6 +279,8 @@ set(FlatBuffers_GRPCTest_SRCS
tests/test_builder.cpp tests/test_builder.cpp
grpc/tests/grpctest.cpp grpc/tests/grpctest.cpp
grpc/tests/message_builder_test.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 # 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 # The small print
Contributions made by corporations are covered by a different agreement than Contributions made by corporations are covered by a different agreement than
the one above, the Software Grant and Corporate Contributor License Agreement. 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| Pod::Spec.new do |s|
s.name = 'FlatBuffers' s.name = 'FlatBuffers'
s.version = '25.2.10' s.version = '25.9.23'
s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
s.description = "FlatBuffers is a cross platform serialization library architected for s.description = "FlatBuffers is a cross platform serialization library architected for

View File

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

View File

@@ -20,17 +20,61 @@ import PackageDescription
let package = Package( let package = Package(
name: "FlatBuffers", name: "FlatBuffers",
platforms: [ platforms: [
.iOS(.v11), .iOS(.v12),
.macOS(.v10_14), .macOS(.v10_14),
], ],
products: [ products: [
.library( .library(
name: "FlatBuffers", name: "FlatBuffers",
targets: ["FlatBuffers"]), targets: ["FlatBuffers"]),
.library(
name: "FlexBuffers",
targets: ["FlexBuffers"]),
], ],
dependencies: .dependencies,
targets: [ targets: [
.target( .target(
name: "FlatBuffers", name: "FlatBuffers",
dependencies: [], dependencies: ["Common"],
path: "swift/Sources"), 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) ![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 // automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_ #ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
#define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_ #define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_
@@ -27,29 +26,24 @@ struct Animal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
VT_SOUND = 6, VT_SOUND = 6,
VT_WEIGHT = 8 VT_WEIGHT = 8
}; };
const ::flatbuffers::String *name() const { const ::flatbuffers::String* name() const {
return GetPointer<const ::flatbuffers::String *>(VT_NAME); return GetPointer<const ::flatbuffers::String*>(VT_NAME);
} }
const ::flatbuffers::String *sound() const { const ::flatbuffers::String* sound() const {
return GetPointer<const ::flatbuffers::String *>(VT_SOUND); return GetPointer<const ::flatbuffers::String*>(VT_SOUND);
} }
uint16_t weight() const { uint16_t weight() const { return GetField<uint16_t>(VT_WEIGHT, 0); }
return GetField<uint16_t>(VT_WEIGHT, 0); bool Verify(::flatbuffers::Verifier& verifier) const {
} return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&
bool Verify(::flatbuffers::Verifier &verifier) const { verifier.VerifyString(name()) && VerifyOffset(verifier, VT_SOUND) &&
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_SOUND) &&
verifier.VerifyString(sound()) && verifier.VerifyString(sound()) &&
VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) && VerifyField<uint16_t>(verifier, VT_WEIGHT, 2) && verifier.EndTable();
verifier.EndTable();
} }
}; };
struct AnimalBuilder { struct AnimalBuilder {
typedef Animal Table; typedef Animal Table;
::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::FlatBufferBuilder& fbb_;
::flatbuffers::uoffset_t start_; ::flatbuffers::uoffset_t start_;
void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
fbb_.AddOffset(Animal::VT_NAME, name); fbb_.AddOffset(Animal::VT_NAME, name);
@@ -60,8 +54,7 @@ struct AnimalBuilder {
void add_weight(uint16_t weight) { void add_weight(uint16_t weight) {
fbb_.AddElement<uint16_t>(Animal::VT_WEIGHT, weight, 0); fbb_.AddElement<uint16_t>(Animal::VT_WEIGHT, weight, 0);
} }
explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder &_fbb) explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
: fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
} }
::flatbuffers::Offset<Animal> Finish() { ::flatbuffers::Offset<Animal> Finish() {
@@ -72,7 +65,7 @@ struct AnimalBuilder {
}; };
inline ::flatbuffers::Offset<Animal> CreateAnimal( inline ::flatbuffers::Offset<Animal> CreateAnimal(
::flatbuffers::FlatBufferBuilder &_fbb, ::flatbuffers::FlatBufferBuilder& _fbb,
::flatbuffers::Offset<::flatbuffers::String> name = 0, ::flatbuffers::Offset<::flatbuffers::String> name = 0,
::flatbuffers::Offset<::flatbuffers::String> sound = 0, ::flatbuffers::Offset<::flatbuffers::String> sound = 0,
uint16_t weight = 0) { uint16_t weight = 0) {
@@ -84,45 +77,37 @@ inline ::flatbuffers::Offset<Animal> CreateAnimal(
} }
inline ::flatbuffers::Offset<Animal> CreateAnimalDirect( inline ::flatbuffers::Offset<Animal> CreateAnimalDirect(
::flatbuffers::FlatBufferBuilder &_fbb, ::flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr,
const char *name = nullptr, const char* sound = nullptr, uint16_t weight = 0) {
const char *sound = nullptr,
uint16_t weight = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0; auto name__ = name ? _fbb.CreateString(name) : 0;
auto sound__ = sound ? _fbb.CreateString(sound) : 0; auto sound__ = sound ? _fbb.CreateString(sound) : 0;
return com::fbs::app::CreateAnimal( return com::fbs::app::CreateAnimal(_fbb, name__, sound__, weight);
_fbb,
name__,
sound__,
weight);
} }
inline const com::fbs::app::Animal *GetAnimal(const void *buf) { inline const com::fbs::app::Animal* GetAnimal(const void* buf) {
return ::flatbuffers::GetRoot<com::fbs::app::Animal>(buf); return ::flatbuffers::GetRoot<com::fbs::app::Animal>(buf);
} }
inline const com::fbs::app::Animal *GetSizePrefixedAnimal(const void *buf) { inline const com::fbs::app::Animal* GetSizePrefixedAnimal(const void* buf) {
return ::flatbuffers::GetSizePrefixedRoot<com::fbs::app::Animal>(buf); return ::flatbuffers::GetSizePrefixedRoot<com::fbs::app::Animal>(buf);
} }
inline bool VerifyAnimalBuffer( inline bool VerifyAnimalBuffer(::flatbuffers::Verifier& verifier) {
::flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<com::fbs::app::Animal>(nullptr); return verifier.VerifyBuffer<com::fbs::app::Animal>(nullptr);
} }
inline bool VerifySizePrefixedAnimalBuffer( inline bool VerifySizePrefixedAnimalBuffer(::flatbuffers::Verifier& verifier) {
::flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<com::fbs::app::Animal>(nullptr); return verifier.VerifySizePrefixedBuffer<com::fbs::app::Animal>(nullptr);
} }
inline void FinishAnimalBuffer( inline void FinishAnimalBuffer(
::flatbuffers::FlatBufferBuilder &fbb, ::flatbuffers::FlatBufferBuilder& fbb,
::flatbuffers::Offset<com::fbs::app::Animal> root) { ::flatbuffers::Offset<com::fbs::app::Animal> root) {
fbb.Finish(root); fbb.Finish(root);
} }
inline void FinishSizePrefixedAnimalBuffer( inline void FinishSizePrefixedAnimalBuffer(
::flatbuffers::FlatBufferBuilder &fbb, ::flatbuffers::FlatBufferBuilder& fbb,
::flatbuffers::Offset<com::fbs::app::Animal> root) { ::flatbuffers::Offset<com::fbs::app::Animal> root) {
fbb.FinishSizePrefixed(root); fbb.FinishSizePrefixed(root);
} }

View File

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

View File

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

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

View File

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

View File

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

View File

@@ -15,8 +15,8 @@
*/ */
import Benchmark import Benchmark
import CoreFoundation
import FlatBuffers import FlatBuffers
import Foundation
@usableFromInline @usableFromInline
struct AA: NativeStruct { struct AA: NativeStruct {
@@ -29,6 +29,15 @@ struct AA: NativeStruct {
} }
let benchmarks = { 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 ints: [Int] = Array(repeating: 42, count: 100)
let bytes: [UInt8] = Array(repeating: 42, count: 100) let bytes: [UInt8] = Array(repeating: 42, count: 100)
let str10 = (0...9).map { _ -> String in "x" }.joined() let str10 = (0...9).map { _ -> String in "x" }.joined()
@@ -73,12 +82,25 @@ let benchmarks = {
Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in
for _ in benchmark.scaledIterations { 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 Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
var fb = FlatBufferBuilder(initialSize: 1_024_000_000) var fb = FlatBufferBuilder(initialSize: oneGB)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.clear()) blackHole(fb.clear())
@@ -86,7 +108,7 @@ let benchmarks = {
} }
Benchmark("Strings 10") { benchmark in Benchmark("Strings 10") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10)) blackHole(fb.create(string: str10))
@@ -94,7 +116,7 @@ let benchmarks = {
} }
Benchmark("Strings 100") { benchmark in Benchmark("Strings 100") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100)) blackHole(fb.create(string: str100))
@@ -102,7 +124,7 @@ let benchmarks = {
} }
Benchmark("Vector 1 Bytes") { benchmark in Benchmark("Vector 1 Bytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes)) blackHole(fb.createVector(bytes: bytes))
@@ -110,7 +132,7 @@ let benchmarks = {
} }
Benchmark("Vector 1 Ints") { benchmark in Benchmark("Vector 1 Ints") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints)) blackHole(fb.createVector(ints))
@@ -118,7 +140,7 @@ let benchmarks = {
} }
Benchmark("Vector 100 Ints") { benchmark in Benchmark("Vector 100 Ints") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints)) blackHole(fb.createVector(ints))
@@ -126,7 +148,7 @@ let benchmarks = {
} }
Benchmark("Vector 100 Bytes") { benchmark in Benchmark("Vector 100 Bytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes)) blackHole(fb.createVector(bytes))
@@ -134,7 +156,7 @@ let benchmarks = {
} }
Benchmark("Vector 100 ContiguousBytes") { benchmark in Benchmark("Vector 100 ContiguousBytes") { benchmark in
var fb = FlatBufferBuilder(initialSize: 1<<20) var fb = FlatBufferBuilder(initialSize: 1 << 20)
benchmark.startMeasurement() benchmark.startMeasurement()
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes)) blackHole(fb.createVector(bytes: bytes))
@@ -143,8 +165,8 @@ let benchmarks = {
Benchmark( Benchmark(
"FlatBufferBuilder Add", "FlatBufferBuilder Add",
configuration: kiloConfiguration) configuration: kiloConfiguration
{ benchmark in ) { benchmark in
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32) var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
benchmark.startMeasurement() benchmark.startMeasurement()
for _ in benchmark.scaledIterations { 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 Benchmark("Structs") { benchmark in
let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024 let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024
var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600)) var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600))
@@ -176,7 +218,7 @@ let benchmarks = {
let start = fb.startTable(with: 1) let start = fb.startTable(with: 1)
fb.add(offset: vector, at: 4) fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start)) let root = Offset(offset: fb.endTable(at: start))
fb.finish(offset: root) blackHole(fb.finish(offset: root))
} }
Benchmark("Vector of Offsets") { benchmark in Benchmark("Vector of Offsets") { benchmark in
@@ -198,4 +240,11 @@ let benchmarks = {
blackHole(fb.endTable(at: s)) 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( let package = Package(
name: "benchmarks", name: "benchmarks",
platforms: [ platforms: [
.macOS(.v13), .macOS(.v13)
], ],
dependencies: [ dependencies: [
.package(path: "../.."), .package(path: "../.."),
@@ -37,6 +37,6 @@ let package = Package(
], ],
path: "Benchmarks/FlatbuffersBenchmarks", path: "Benchmarks/FlatbuffersBenchmarks",
plugins: [ 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 from cpt.packager import ConanMultiPackager
def get_branch(): def get_branch():
try: 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() line = line.strip()
if line.startswith("*") and " (HEAD detached" not in line: if line.startswith("*") and " (HEAD detached" not in line:
return line.replace("*", "", 1).strip() return line.replace("*", "", 1).strip()
@@ -34,17 +35,25 @@ def get_reference(username):
if __name__ == "__main__": if __name__ == "__main__":
login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel") login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel")
username = os.getenv("CONAN_USERNAME", "google") username = os.getenv("CONAN_USERNAME", "google")
upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers") upload = os.getenv(
stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*") "CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers"
test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package")) )
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) 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, username=username,
login_username=login_username, login_username=login_username,
upload=upload, upload=upload,
stable_branch_pattern=stable_branch_pattern, stable_branch_pattern=stable_branch_pattern,
upload_only_when_stable=upload_only_when_stable, upload_only_when_stable=upload_only_when_stable,
test_folder=test_folder) test_folder=test_folder,
)
builder.add_common_builds(pure_c=False) builder.add_common_builds(pure_c=False)
builder.run() builder.run()

View File

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

View File

@@ -1,11 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Conan recipe package for Google FlatBuffers """Conan recipe package for Google FlatBuffers"""
"""
import os import os
import shutil import shutil
from conans import ConanFile, CMake, tools from conans import CMake, ConanFile, tools
class FlatbuffersConan(ConanFile): class FlatbuffersConan(ConanFile):
@@ -21,23 +20,27 @@ class FlatbuffersConan(ConanFile):
default_options = {"shared": False, "fPIC": True} default_options = {"shared": False, "fPIC": True}
generators = "cmake" generators = "cmake"
exports = "LICENSE" 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): 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("CMakeLists.txt", "CMakeListsOriginal.txt")
shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt") shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
def config_options(self): def config_options(self):
"""Remove fPIC option on Windows platform """Remove fPIC option on Windows platform"""
"""
if self.settings.os == "Windows": if self.settings.os == "Windows":
self.options.remove("fPIC") self.options.remove("fPIC")
def configure_cmake(self): def configure_cmake(self):
"""Create CMake instance and execute configure step """Create CMake instance and execute configure step"""
"""
cmake = CMake(self) cmake = CMake(self)
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
@@ -46,30 +49,35 @@ class FlatbuffersConan(ConanFile):
return cmake return cmake
def build(self): def build(self):
"""Configure, build and install FlatBuffers using CMake. """Configure, build and install FlatBuffers using CMake."""
"""
cmake = self.configure_cmake() cmake = self.configure_cmake()
cmake.build() cmake.build()
def package(self): def package(self):
"""Copy Flatbuffers' artifacts to package folder """Copy Flatbuffers' artifacts to package folder"""
"""
cmake = self.configure_cmake() cmake = self.configure_cmake()
cmake.install() cmake.install()
self.copy(pattern="LICENSE", dst="licenses") 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="flathash*", dst="bin", src="bin")
self.copy(pattern="flatc*", dst="bin", src="bin") self.copy(pattern="flatc*", dst="bin", src="bin")
if self.settings.os == "Windows" and self.options.shared: if self.settings.os == "Windows" and self.options.shared:
if self.settings.compiler == "Visual Studio": if self.settings.compiler == "Visual Studio":
shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name), shutil.move(
os.path.join(self.package_folder, "bin", "%s.dll" % self.name)) 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": elif self.settings.compiler == "gcc":
shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name), shutil.move(
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name)) 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): 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.cpp_info.libs = tools.collect_libs(self)
self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc") 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 'package:flat_buffers/flat_buffers.dart' as fb;
import './monster_my_game.sample_generated.dart' as my_game; import './monster_my_game.sample_generated.dart' as my_game;
// Example how to use FlatBuffers to create and read binary buffers. // Example how to use FlatBuffers to create and read binary buffers.
@@ -78,7 +79,8 @@ void builderTest() {
builder.finish(monsteroff); builder.finish(monsteroff);
if (verify(builder.buffer)) { if (verify(builder.buffer)) {
print( 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', name: 'Orc',
inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
color: my_game.Color.Red, 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, equippedType: my_game.EquipmentTypeId.Weapon,
equipped: axe, equipped: axe,
); );
@@ -108,7 +113,8 @@ void objectBuilderTest() {
// Instead, we're going to access it right away (as if we just received it). // Instead, we're going to access it right away (as if we just received it).
if (verify(buffer)) { if (verify(buffer)) {
print( 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; library my_game.sample;
import 'dart:typed_data' show Uint8List; 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 { class Color {
final int value; final int value;
@@ -29,10 +29,7 @@ class Color {
static const Color Red = Color._(0); static const Color Red = Color._(0);
static const Color Green = Color._(1); static const Color Green = Color._(1);
static const Color Blue = Color._(2); static const Color Blue = Color._(2);
static const Map<int, Color> values = { static const Map<int, Color> values = {0: Red, 1: Green, 2: Blue};
0: Red,
1: Green,
2: Blue};
static const fb.Reader<Color> reader = _ColorReader(); static const fb.Reader<Color> reader = _ColorReader();
@@ -60,7 +57,9 @@ class EquipmentTypeId {
factory EquipmentTypeId.fromValue(int value) { factory EquipmentTypeId.fromValue(int value) {
final result = values[value]; final result = values[value];
if (result == null) { if (result == null) {
throw StateError('Invalid value $value for bit flag enum EquipmentTypeId'); throw StateError(
'Invalid value $value for bit flag enum EquipmentTypeId',
);
} }
return result; return result;
} }
@@ -74,9 +73,7 @@ class EquipmentTypeId {
static const EquipmentTypeId NONE = EquipmentTypeId._(0); static const EquipmentTypeId NONE = EquipmentTypeId._(0);
static const EquipmentTypeId Weapon = EquipmentTypeId._(1); static const EquipmentTypeId Weapon = EquipmentTypeId._(1);
static const Map<int, EquipmentTypeId> values = { static const Map<int, EquipmentTypeId> values = {0: NONE, 1: Weapon};
0: NONE,
1: Weapon};
static const fb.Reader<EquipmentTypeId> reader = _EquipmentTypeIdReader(); static const fb.Reader<EquipmentTypeId> reader = _EquipmentTypeIdReader();
@@ -122,8 +119,7 @@ class _Vec3Reader extends fb.StructReader<Vec3> {
int get size => 12; int get size => 12;
@override @override
Vec3 createObject(fb.BufferContext bc, int offset) => Vec3 createObject(fb.BufferContext bc, int offset) => Vec3._(bc, offset);
Vec3._(bc, offset);
} }
class Vec3Builder { class Vec3Builder {
@@ -137,7 +133,6 @@ class Vec3Builder {
fbBuilder.putFloat32(x); fbBuilder.putFloat32(x);
return fbBuilder.offset; return fbBuilder.offset;
} }
} }
class Vec3ObjectBuilder extends fb.ObjectBuilder { class Vec3ObjectBuilder extends fb.ObjectBuilder {
@@ -145,11 +140,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
final double _y; final double _y;
final double _z; final double _z;
Vec3ObjectBuilder({ Vec3ObjectBuilder({required double x, required double y, required double z})
required double x,
required double y,
required double z,
})
: _x = x, : _x = x,
_y = y, _y = y,
_z = z; _z = z;
@@ -171,6 +162,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer; return fbBuilder.buffer;
} }
} }
class Monster { class Monster {
Monster._(this._bc, this._bcOffset); Monster._(this._bc, this._bcOffset);
factory Monster(List<int> bytes) { factory Monster(List<int> bytes) {
@@ -186,18 +178,30 @@ class Monster {
Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4); Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4);
int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150); int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150);
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100); int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
String? get name => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10); String? get name =>
List<int>? get inventory => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14); const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10);
Color get color => Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2)); List<int>? get inventory =>
List<Weapon>? get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGetNullable(_bc, _bcOffset, 18); const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14);
EquipmentTypeId? get equippedType => EquipmentTypeId._createOrNull(const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 20)); 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 { dynamic get equipped {
switch (equippedType?.value) { switch (equippedType?.value) {
case 1: return Weapon.reader.vTableGetNullable(_bc, _bcOffset, 22); case 1:
default: return null; 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 @override
String toString() { String toString() {
@@ -226,38 +230,47 @@ class MonsterBuilder {
fbBuilder.addStruct(0, offset); fbBuilder.addStruct(0, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addMana(int? mana) { int addMana(int? mana) {
fbBuilder.addInt16(1, mana); fbBuilder.addInt16(1, mana);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addHp(int? hp) { int addHp(int? hp) {
fbBuilder.addInt16(2, hp); fbBuilder.addInt16(2, hp);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addNameOffset(int? offset) { int addNameOffset(int? offset) {
fbBuilder.addOffset(3, offset); fbBuilder.addOffset(3, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addInventoryOffset(int? offset) { int addInventoryOffset(int? offset) {
fbBuilder.addOffset(5, offset); fbBuilder.addOffset(5, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addColor(Color? color) { int addColor(Color? color) {
fbBuilder.addInt8(6, color?.value); fbBuilder.addInt8(6, color?.value);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addWeaponsOffset(int? offset) { int addWeaponsOffset(int? offset) {
fbBuilder.addOffset(7, offset); fbBuilder.addOffset(7, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addEquippedType(EquipmentTypeId? equippedType) { int addEquippedType(EquipmentTypeId? equippedType) {
fbBuilder.addUint8(8, equippedType?.value); fbBuilder.addUint8(8, equippedType?.value);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addEquippedOffset(int? offset) { int addEquippedOffset(int? offset) {
fbBuilder.addOffset(9, offset); fbBuilder.addOffset(9, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addPathOffset(int? offset) { int addPathOffset(int? offset) {
fbBuilder.addOffset(10, offset); fbBuilder.addOffset(10, offset);
return fbBuilder.offset; return fbBuilder.offset;
@@ -291,8 +304,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
EquipmentTypeId? equippedType, EquipmentTypeId? equippedType,
dynamic equipped, dynamic equipped,
List<Vec3ObjectBuilder>? path, List<Vec3ObjectBuilder>? path,
}) }) : _pos = pos,
: _pos = pos,
_mana = mana, _mana = mana,
_hp = hp, _hp = hp,
_name = name, _name = name,
@@ -306,14 +318,20 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
/// Finish building, and store into the [fbBuilder]. /// Finish building, and store into the [fbBuilder].
@override @override
int finish(fb.Builder fbBuilder) { int finish(fb.Builder fbBuilder) {
final int? nameOffset = _name == null ? null final int? nameOffset = _name == null
? null
: fbBuilder.writeString(_name!); : fbBuilder.writeString(_name!);
final int? inventoryOffset = _inventory == null ? null final int? inventoryOffset = _inventory == null
? null
: fbBuilder.writeListUint8(_inventory!); : fbBuilder.writeListUint8(_inventory!);
final int? weaponsOffset = _weapons == null ? null final int? weaponsOffset = _weapons == null
: fbBuilder.writeList(_weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList()); ? null
: fbBuilder.writeList(
_weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList(),
);
final int? equippedOffset = _equipped?.getOrCreateOffset(fbBuilder); final int? equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
final int? pathOffset = _path == null ? null final int? pathOffset = _path == null
? null
: fbBuilder.writeListOfStructs(_path!); : fbBuilder.writeListOfStructs(_path!);
fbBuilder.startTable(10); fbBuilder.startTable(10);
if (_pos != null) { if (_pos != null) {
@@ -339,6 +357,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
return fbBuilder.buffer; return fbBuilder.buffer;
} }
} }
class Weapon { class Weapon {
Weapon._(this._bc, this._bcOffset); Weapon._(this._bc, this._bcOffset);
factory Weapon(List<int> bytes) { factory Weapon(List<int> bytes) {
@@ -351,7 +370,8 @@ class Weapon {
final fb.BufferContext _bc; final fb.BufferContext _bc;
final int _bcOffset; 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); int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 0);
@override @override
@@ -364,8 +384,7 @@ class _WeaponReader extends fb.TableReader<Weapon> {
const _WeaponReader(); const _WeaponReader();
@override @override
Weapon createObject(fb.BufferContext bc, int offset) => Weapon createObject(fb.BufferContext bc, int offset) => Weapon._(bc, offset);
Weapon._(bc, offset);
} }
class WeaponBuilder { class WeaponBuilder {
@@ -381,6 +400,7 @@ class WeaponBuilder {
fbBuilder.addOffset(0, offset); fbBuilder.addOffset(0, offset);
return fbBuilder.offset; return fbBuilder.offset;
} }
int addDamage(int? damage) { int addDamage(int? damage) {
fbBuilder.addInt16(1, damage); fbBuilder.addInt16(1, damage);
return fbBuilder.offset; return fbBuilder.offset;
@@ -395,17 +415,15 @@ class WeaponObjectBuilder extends fb.ObjectBuilder {
final String? _name; final String? _name;
final int? _damage; final int? _damage;
WeaponObjectBuilder({ WeaponObjectBuilder({String? name, int? damage})
String? name,
int? damage,
})
: _name = name, : _name = name,
_damage = damage; _damage = damage;
/// Finish building, and store into the [fbBuilder]. /// Finish building, and store into the [fbBuilder].
@override @override
int finish(fb.Builder fbBuilder) { int finish(fb.Builder fbBuilder) {
final int? nameOffset = _name == null ? null final int? nameOffset = _name == null
? null
: fbBuilder.writeString(_name!); : fbBuilder.writeString(_name!);
fbBuilder.startTable(2); fbBuilder.startTable(2);
fbBuilder.addOffset(0, nameOffset); fbBuilder.addOffset(0, nameOffset);

View File

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

View File

@@ -107,8 +107,11 @@ class Builder {
final newOffset = _newOffset(length + 1); final newOffset = _newOffset(length + 1);
_pushBuffer(utf8String); _pushBuffer(utf8String);
_offset = newOffset; _offset = newOffset;
final stackValue = final stackValue = _StackValue.withOffset(
_StackValue.withOffset(stringOffset, ValueType.String, bitWidth); stringOffset,
ValueType.String,
bitWidth,
);
_stack.add(stackValue); _stack.add(stackValue);
_stringCache[value] = stackValue; _stringCache[value] = stackValue;
} }
@@ -128,8 +131,11 @@ class Builder {
final newOffset = _newOffset(length + 1); final newOffset = _newOffset(length + 1);
_pushBuffer(utf8String); _pushBuffer(utf8String);
_offset = newOffset; _offset = newOffset;
final stackValue = final stackValue = _StackValue.withOffset(
_StackValue.withOffset(keyOffset, ValueType.Key, BitWidth.width8); keyOffset,
ValueType.Key,
BitWidth.width8,
);
_stack.add(stackValue); _stack.add(stackValue);
_keyCache[value] = stackValue; _keyCache[value] = stackValue;
} }
@@ -147,8 +153,11 @@ class Builder {
final newOffset = _newOffset(length); final newOffset = _newOffset(length);
_pushBuffer(value.asUint8List()); _pushBuffer(value.asUint8List());
_offset = newOffset; _offset = newOffset;
final stackValue = final stackValue = _StackValue.withOffset(
_StackValue.withOffset(blobOffset, ValueType.Blob, bitWidth); blobOffset,
ValueType.Blob,
bitWidth,
);
_stack.add(stackValue); _stack.add(stackValue);
} }
@@ -170,7 +179,10 @@ class Builder {
final valueOffset = _offset; final valueOffset = _offset;
_pushBuffer(stackValue.asU8List(stackValue.width)); _pushBuffer(stackValue.asU8List(stackValue.width));
final stackOffset = _StackValue.withOffset( final stackOffset = _StackValue.withOffset(
valueOffset, ValueType.IndirectInt, stackValue.width); valueOffset,
ValueType.IndirectInt,
stackValue.width,
);
_stack.add(stackOffset); _stack.add(stackOffset);
_offset = newOffset; _offset = newOffset;
if (cache) { if (cache) {
@@ -195,7 +207,10 @@ class Builder {
final valueOffset = _offset; final valueOffset = _offset;
_pushBuffer(stackValue.asU8List(stackValue.width)); _pushBuffer(stackValue.asU8List(stackValue.width));
final stackOffset = _StackValue.withOffset( final stackOffset = _StackValue.withOffset(
valueOffset, ValueType.IndirectFloat, stackValue.width); valueOffset,
ValueType.IndirectFloat,
stackValue.width,
);
_stack.add(stackOffset); _stack.add(stackOffset);
_offset = newOffset; _offset = newOffset;
if (cache) { if (cache) {
@@ -252,9 +267,10 @@ class Builder {
tmp._offset = _offset; tmp._offset = _offset;
tmp._stack = List.from(_stack); tmp._stack = List.from(_stack);
tmp._stackPointers = List.from(_stackPointers); tmp._stackPointers = List.from(_stackPointers);
tmp._buffer.buffer tmp._buffer.buffer.asUint8List().setAll(
.asUint8List() 0,
.setAll(0, _buffer.buffer.asUint8List(0, _offset)); _buffer.buffer.asUint8List(0, _offset),
);
for (var i = 0; i < tmp._stackPointers.length; i++) { for (var i = 0; i < tmp._stackPointers.length; i++) {
tmp.end(); tmp.end();
} }
@@ -271,7 +287,8 @@ class Builder {
if (_stackPointers.isNotEmpty && _stackPointers.last.isVector == false) { if (_stackPointers.isNotEmpty && _stackPointers.last.isVector == false) {
if (_stack.last.type != ValueType.Key) { if (_stack.last.type != ValueType.Key) {
throw StateError( 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() { void _finish() {
if (_stack.length != 1) { if (_stack.length != 1) {
throw StateError( 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 value = _stack[0];
final byteWidth = _align(value.elementWidth(_offset, 0)); final byteWidth = _align(value.elementWidth(_offset, 0));
@@ -298,8 +316,12 @@ class Builder {
_finished = true; _finished = true;
} }
_StackValue _createVector(int start, int vecLength, int step, _StackValue _createVector(
[_StackValue? keys]) { int start,
int vecLength,
int step, [
_StackValue? keys,
]) {
var bitWidth = BitWidthUtil.uwidth(vecLength); var bitWidth = BitWidthUtil.uwidth(vecLength);
var prefixElements = 1; var prefixElements = 1;
if (keys != null) { if (keys != null) {
@@ -326,7 +348,8 @@ class Builder {
} }
} }
final byteWidth = _align(bitWidth); final byteWidth = _align(bitWidth);
final fix = typed & ValueTypeUtils.isNumber(vectorType) && final fix =
typed & ValueTypeUtils.isNumber(vectorType) &&
vecLength >= 2 && vecLength >= 2 &&
vecLength <= 4; vecLength <= 4;
if (keys != null) { if (keys != null) {
@@ -349,8 +372,10 @@ class Builder {
return _StackValue.withOffset(vecOffset, ValueType.Map, bitWidth); return _StackValue.withOffset(vecOffset, ValueType.Map, bitWidth);
} }
if (typed) { if (typed) {
final vType = final vType = ValueTypeUtils.toTypedVector(
ValueTypeUtils.toTypedVector(vectorType, fix ? vecLength : 0); vectorType,
fix ? vecLength : 0,
);
return _StackValue.withOffset(vecOffset, vType, bitWidth); return _StackValue.withOffset(vecOffset, vType, bitWidth);
} }
return _StackValue.withOffset(vecOffset, ValueType.Vector, bitWidth); return _StackValue.withOffset(vecOffset, ValueType.Vector, bitWidth);
@@ -366,7 +391,8 @@ class Builder {
void _sortKeysAndEndMap(_StackPointer pointer) { void _sortKeysAndEndMap(_StackPointer pointer) {
if (((_stack.length - pointer.stackPosition) & 1) == 1) { if (((_stack.length - pointer.stackPosition) & 1) == 1) {
throw StateError( 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; var sorted = true;
@@ -412,8 +438,12 @@ class Builder {
keysStackValue = _createVector(pointer.stackPosition, vecLength, 2); keysStackValue = _createVector(pointer.stackPosition, vecLength, 2);
_keyVectorCache[keysHash] = keysStackValue; _keyVectorCache[keysHash] = keysStackValue;
} }
final vec = final vec = _createVector(
_createVector(pointer.stackPosition + 1, vecLength, 2, keysStackValue); pointer.stackPosition + 1,
vecLength,
2,
keysStackValue,
);
_stack.removeRange(pointer.stackPosition, _stack.length); _stack.removeRange(pointer.stackPosition, _stack.length);
_stack.add(vec); _stack.add(vec);
} }
@@ -421,7 +451,8 @@ class Builder {
bool _shouldFlip(_StackValue v1, _StackValue v2) { bool _shouldFlip(_StackValue v1, _StackValue v2) {
if (v1.type != ValueType.Key || v2.type != ValueType.Key) { if (v1.type != ValueType.Key || v2.type != ValueType.Key) {
throw StateError( 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; late int c1, c2;
@@ -450,7 +481,8 @@ class Builder {
_writeUInt(relativeOffset, byteWidth); _writeUInt(relativeOffset, byteWidth);
} else { } else {
throw StateError( 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 { } else {
_pushBuffer(value.asU8List(BitWidthUtil.fromByteWidth(byteWidth))); _pushBuffer(value.asU8List(BitWidthUtil.fromByteWidth(byteWidth)));
@@ -523,9 +555,7 @@ class _StackValue {
final ValueType _type; final ValueType _type;
final BitWidth _width; final BitWidth _width;
_StackValue.withNull() _StackValue.withNull() : _type = ValueType.Null, _width = BitWidth.width8;
: _type = ValueType.Null,
_width = BitWidth.width8;
_StackValue.withInt(int value) _StackValue.withInt(int value)
: _type = ValueType.Int, : _type = ValueType.Int,
@@ -562,16 +592,16 @@ class _StackValue {
final offset = _offset!; final offset = _offset!;
for (var i = 0; i < 4; i++) { for (var i = 0; i < 4; i++) {
final width = 1 << i; final width = 1 << i;
final bitWidth = BitWidthUtil.uwidth(size + final bitWidth = BitWidthUtil.uwidth(
BitWidthUtil.paddingSize(size, width) + size + BitWidthUtil.paddingSize(size, width) + index * width - offset,
index * width - );
offset);
if (1 << bitWidth.index == width) { if (1 << bitWidth.index == width) {
return bitWidth; return bitWidth;
} }
} }
throw StateError( 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) { List<int> asU8List(BitWidth width) {
@@ -619,7 +649,8 @@ class _StackValue {
} }
throw StateError( 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 { ValueType get type {

View File

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

View File

@@ -86,7 +86,8 @@ enum ValueType {
VectorFloat, VectorFloat,
VectorKey, VectorKey,
@Deprecated( @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, VectorString,
VectorInt2, VectorInt2,
VectorUInt2, VectorUInt2,
@@ -99,7 +100,7 @@ enum ValueType {
VectorFloat4, VectorFloat4,
Blob, Blob,
Bool, Bool,
VectorBool VectorBool,
} }
class ValueTypeUtils { class ValueTypeUtils {
@@ -153,31 +154,37 @@ class ValueTypeUtils {
static ValueType toTypedVector(ValueType self, int length) { static ValueType toTypedVector(ValueType self, int length) {
if (length == 0) { if (length == 0) {
return ValueTypeUtils.fromInt( return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt)); toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt),
);
} }
if (length == 2) { if (length == 2) {
return ValueTypeUtils.fromInt( return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2)); toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2),
);
} }
if (length == 3) { if (length == 3) {
return ValueTypeUtils.fromInt( return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3)); toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3),
);
} }
if (length == 4) { if (length == 4) {
return ValueTypeUtils.fromInt( 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()); throw Exception('unexpected length ' + length.toString());
} }
static ValueType typedVectorElementType(ValueType self) { static ValueType typedVectorElementType(ValueType self) {
return ValueTypeUtils.fromInt( return ValueTypeUtils.fromInt(
toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int)); toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int),
);
} }
static ValueType fixedTypedVectorElementType(ValueType self) { static ValueType fixedTypedVectorElementType(ValueType self) {
return ValueTypeUtils.fromInt( 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) { static int fixedTypedVectorElementSize(ValueType self) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -48,116 +48,210 @@ void main() {
expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt), isFalse); expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt), isFalse);
}); });
test('to typed vector', () { test('to typed vector', () {
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 0), expect(
equals(ValueType.VectorInt)); ValueTypeUtils.toTypedVector(ValueType.Int, 0),
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 0), equals(ValueType.VectorInt),
equals(ValueType.VectorUInt)); );
expect(ValueTypeUtils.toTypedVector(ValueType.Bool, 0), expect(
equals(ValueType.VectorBool)); ValueTypeUtils.toTypedVector(ValueType.UInt, 0),
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 0), equals(ValueType.VectorUInt),
equals(ValueType.VectorFloat)); );
expect(ValueTypeUtils.toTypedVector(ValueType.Key, 0), expect(
equals(ValueType.VectorKey)); ValueTypeUtils.toTypedVector(ValueType.Bool, 0),
expect(ValueTypeUtils.toTypedVector(ValueType.String, 0), equals(ValueType.VectorBool),
equals(ValueType.VectorString)); );
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), expect(
equals(ValueType.VectorInt2)); ValueTypeUtils.toTypedVector(ValueType.Int, 2),
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 2), equals(ValueType.VectorInt2),
equals(ValueType.VectorUInt2)); );
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 2), expect(
equals(ValueType.VectorFloat2)); ValueTypeUtils.toTypedVector(ValueType.UInt, 2),
equals(ValueType.VectorUInt2),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 2),
equals(ValueType.VectorFloat2),
);
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 3), expect(
equals(ValueType.VectorInt3)); ValueTypeUtils.toTypedVector(ValueType.Int, 3),
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 3), equals(ValueType.VectorInt3),
equals(ValueType.VectorUInt3)); );
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 3), expect(
equals(ValueType.VectorFloat3)); ValueTypeUtils.toTypedVector(ValueType.UInt, 3),
equals(ValueType.VectorUInt3),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 3),
equals(ValueType.VectorFloat3),
);
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 4), expect(
equals(ValueType.VectorInt4)); ValueTypeUtils.toTypedVector(ValueType.Int, 4),
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 4), equals(ValueType.VectorInt4),
equals(ValueType.VectorUInt4)); );
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 4), expect(
equals(ValueType.VectorFloat4)); ValueTypeUtils.toTypedVector(ValueType.UInt, 4),
equals(ValueType.VectorUInt4),
);
expect(
ValueTypeUtils.toTypedVector(ValueType.Float, 4),
equals(ValueType.VectorFloat4),
);
}); });
test('typed vector element type', () { test('typed vector element type', () {
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorInt), expect(
equals(ValueType.Int)); ValueTypeUtils.typedVectorElementType(ValueType.VectorInt),
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt), equals(ValueType.Int),
equals(ValueType.UInt)); );
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat), expect(
equals(ValueType.Float)); ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt),
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorString), equals(ValueType.UInt),
equals(ValueType.String)); );
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorKey), expect(
equals(ValueType.Key)); ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat),
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorBool), equals(ValueType.Float),
equals(ValueType.Bool)); );
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', () { test('fixed typed vector element type', () {
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2), expect(
equals(ValueType.Int)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2),
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3), equals(ValueType.Int),
equals(ValueType.Int)); );
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4), expect(
equals(ValueType.Int)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3),
equals(ValueType.Int),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4),
equals(ValueType.Int),
);
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2), expect(
equals(ValueType.UInt)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2),
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3), equals(ValueType.UInt),
equals(ValueType.UInt)); );
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4), expect(
equals(ValueType.UInt)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3),
equals(ValueType.UInt),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4),
equals(ValueType.UInt),
);
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2), expect(
equals(ValueType.Float)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2),
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3), equals(ValueType.Float),
equals(ValueType.Float)); );
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4), expect(
equals(ValueType.Float)); ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3),
equals(ValueType.Float),
);
expect(
ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4),
equals(ValueType.Float),
);
}); });
test('fixed typed vector element size', () { test('fixed typed vector element size', () {
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2), expect(
equals(2)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2),
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3), equals(2),
equals(3)); );
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4), expect(
equals(4)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4),
equals(4),
);
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2), expect(
equals(2)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2),
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3), equals(2),
equals(3)); );
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4), expect(
equals(4)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4),
equals(4),
);
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2), expect(
equals(2)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2),
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3), equals(2),
equals(3)); );
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4), expect(
equals(4)); ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3),
equals(3),
);
expect(
ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4),
equals(4),
);
}); });
test('packed type', () { test('packed type', () {
expect( expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8), equals(0)); ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8),
equals(0),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16), equals(1)); ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16),
equals(1),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32), equals(2)); ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32),
equals(2),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64), equals(3)); ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64),
equals(3),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8), equals(4)); ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8),
equals(4),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16), equals(5)); ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16),
equals(5),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32), equals(6)); ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32),
equals(6),
);
expect( expect(
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64), equals(7)); ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64),
equals(7),
);
}); });
test('bit width', () { test('bit width', () {
expect(BitWidthUtil.width(0), BitWidth.width8); 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 // ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names
import 'dart:typed_data' show Uint8List; 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_test2_my_game.other_name_space_generated.dart'
import './include_test2_my_game.other_name_space_generated.dart' as my_game_other_name_space; as my_game_other_name_space;
class TableA { class TableA {
TableA._(this._bc, this._bcOffset); TableA._(this._bc, this._bcOffset);
@@ -19,15 +20,17 @@ class TableA {
final fb.BufferContext _bc; final fb.BufferContext _bc;
final int _bcOffset; 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 @override
String toString() { String toString() {
return 'TableA{b: ${b}}'; return 'TableA{b: ${b}}';
} }
TableAT unpack() => TableAT( TableAT unpack() => TableAT(b: b?.unpack());
b: b?.unpack());
static int pack(fb.Builder fbBuilder, TableAT? object) { static int pack(fb.Builder fbBuilder, TableAT? object) {
if (object == null) return 0; if (object == null) return 0;
@@ -38,8 +41,7 @@ class TableA {
class TableAT implements fb.Packable { class TableAT implements fb.Packable {
my_game_other_name_space.TableBT? b; my_game_other_name_space.TableBT? b;
TableAT({ TableAT({this.b});
this.b});
@override @override
int pack(fb.Builder fbBuilder) { int pack(fb.Builder fbBuilder) {
@@ -59,8 +61,7 @@ class _TableAReader extends fb.TableReader<TableA> {
const _TableAReader(); const _TableAReader();
@override @override
TableA createObject(fb.BufferContext bc, int offset) => TableA createObject(fb.BufferContext bc, int offset) => TableA._(bc, offset);
TableA._(bc, offset);
} }
class TableABuilder { class TableABuilder {
@@ -85,9 +86,7 @@ class TableABuilder {
class TableAObjectBuilder extends fb.ObjectBuilder { class TableAObjectBuilder extends fb.ObjectBuilder {
final my_game_other_name_space.TableBObjectBuilder? _b; final my_game_other_name_space.TableBObjectBuilder? _b;
TableAObjectBuilder({ TableAObjectBuilder({my_game_other_name_space.TableBObjectBuilder? b})
my_game_other_name_space.TableBObjectBuilder? b,
})
: _b = b; : _b = b;
/// Finish building, and store into the [fbBuilder]. /// Finish building, and store into the [fbBuilder].

View File

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

View File

@@ -4,12 +4,12 @@
library my_game.example2; library my_game.example2;
import 'dart:typed_data' show Uint8List; 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 './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 './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 { class Monster {
Monster._(this._bc, this._bcOffset); Monster._(this._bc, this._bcOffset);
@@ -23,7 +23,6 @@ class Monster {
final fb.BufferContext _bc; final fb.BufferContext _bc;
final int _bcOffset; final int _bcOffset;
@override @override
String toString() { String toString() {
return 'Monster{}'; return 'Monster{}';
@@ -59,7 +58,6 @@ class _MonsterReader extends fb.TableReader<Monster> {
} }
class MonsterObjectBuilder extends fb.ObjectBuilder { class MonsterObjectBuilder extends fb.ObjectBuilder {
MonsterObjectBuilder(); MonsterObjectBuilder();
/// Finish building, and store into the [fbBuilder]. /// 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; library my_game;
import 'dart:typed_data' show Uint8List; 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 './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 './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 { class InParentNamespace {
InParentNamespace._(this._bc, this._bcOffset); InParentNamespace._(this._bc, this._bcOffset);
@@ -23,7 +23,6 @@ class InParentNamespace {
final fb.BufferContext _bc; final fb.BufferContext _bc;
final int _bcOffset; final int _bcOffset;
@override @override
String toString() { String toString() {
return 'InParentNamespace{}'; return 'InParentNamespace{}';
@@ -59,7 +58,6 @@ class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
} }
class InParentNamespaceObjectBuilder extends fb.ObjectBuilder { class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
InParentNamespaceObjectBuilder(); InParentNamespaceObjectBuilder();
/// Finish building, and store into the [fbBuilder]. /// Finish building, and store into the [fbBuilder].

View File

@@ -6,7 +6,7 @@ https://flatbuffers.dev.
## Local Building ## 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__ __tl;dr__

View File

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

View File

@@ -131,7 +131,7 @@ list of `FILES...`.
- `--gen-mutable` : Generate additional non-const accessors for mutating - `--gen-mutable` : Generate additional non-const accessors for mutating
FlatBuffers in-place. 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++. - `--gen-name-strings` : Generate type name functions for C++.
@@ -259,6 +259,8 @@ list of `FILES...`.
- `--python-typing` : Generate Python type annotations - `--python-typing` : Generate Python type annotations
- `--python-decode-obj-api-strings` : Decode bytes automaticaly with utf-8
Additional gRPC options: Additional gRPC options:
- `--grpc-filename-suffix`: `[C++]` An optional suffix for the generated - `--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** - :material-memory:{ .lg .middle } **Memory Efficiency and Speed**
--- ---
The only memory needed to access your data is that of the buffer. No heap is The only memory needed to access your data is that of the buffer.
required. No heap is required.
- :material-compare-horizontal:{ .lg .middle } **Backwards and Forwards - :material-compare-horizontal:{ .lg .middle } **Backwards and Forwards
Compatibility** Compatibility**
--- ---
The only memory needed to access your data is that of the buffer. No heap is FlatBuffers enables the schema to evolve over time while still maintaining
required. forwards and backwards compatibility with old flatbuffers.
- :material-scale-off:{ .lg .middle } **Small Footprint** - :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: e.g. for `Monster`, you can call:
```cpp ```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. 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: pass the contents of to the `GetRootAsMonster` function:
~~~{.php} ~~~{.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: // Here is an example:
function __autoload($class_name) { function __autoload($class_name) {
// The last segment of the class name matches the file 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. // Read the contents of the FlatBuffer binary file.
$filename = "monster.dat"; $filename = "monster.dat";
$handle = fopen($filename, "rb"); $handle = fopen($filename, "rb");
$contents = $fread($handle, filesize($filename)); $contents = fread($handle, filesize($filename));
fclose($handle); fclose($handle);
// Pass the contents to `GetRootAsMonster`. // 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 when no other references to the `FlatBufferBuilder` exist, and may not be copied
within the same thread, let alone to a second thread. 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 ## Useful tools created by others
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler * [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") let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
guard let data = try? Data(contentsOf: url) else { return } 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: 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: code:
```sh ```sh
./flatc --cpp --rust mosnter.fbs ./flatc --cpp --rust monster.fbs
``` ```
Which generates `monster_generated.h` and `monster_generated.rs` files. Which generates `monster_generated.h` and `monster_generated.rs` files.

View File

@@ -2011,6 +2011,8 @@ like so:
let buf = builder.sizedByteArray let buf = builder.sizedByteArray
// or you can use to get an object of type Data // or you can use to get an object of type Data
let bufData = ByteBuffer(data: builder.data) let bufData = ByteBuffer(data: builder.data)
// or
let buf = builder.sizedBuffer
``` ```
=== "TypeScript" === "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. // logically-equal vtables will be deduplicated.
// //
// A vtable has the following format: // A vtable has the following format:
//
// <VOffsetT: size of the vtable in bytes, including this value> // <VOffsetT: size of the vtable in bytes, including this value>
// <VOffsetT: size of the object in bytes, including the vtable offset> // <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 // <VOffsetT: offset for a field> * N, where N is the number of fields in
// the schema for this type. Includes deprecated fields. // the schema for this type. Includes deprecated fields.
//
// Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide. // Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide.
// //
// An object has the following format: // An object has the following format:
//
// <SOffsetT: offset to this object's vtable (may be negative)> // <SOffsetT: offset to this object's vtable (may be negative)>
// <byte: data>+ // <byte: data>+
func (b *Builder) WriteVtable() (n UOffsetT) { func (b *Builder) WriteVtable() (n UOffsetT) {
@@ -296,6 +299,7 @@ func (b *Builder) PrependUOffsetT(off UOffsetT) {
// StartVector initializes bookkeeping for writing a new vector. // StartVector initializes bookkeeping for writing a new vector.
// //
// A vector has the following format: // A vector has the following format:
//
// <UOffsetT: number of elements in this vector> // <UOffsetT: number of elements in this vector>
// <T: data>+, where T is the type of elements of this vector. // <T: data>+, where T is the type of elements of this vector.
func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT { func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT {

View File

@@ -1,7 +1,17 @@
package flatbuffers package flatbuffers
// Codec implements gRPC-go Codec which is used to encode and decode messages. import "errors"
var Codec = "flatbuffers"
var (
// Codec implements gRPC-go Codec which is used to encode and decode messages.
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 // FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
// that implementations of this interface must be thread safe; a Codec's // 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. // Unmarshal parses the wire format into v.
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error { 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 return nil
} }

View File

@@ -3,8 +3,8 @@
This directory is a repository for the generated files of `flatc`. 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 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 changes affect the generated output. It's also useful as a reference to show
as how things work across various languages. how things work across various languages.
These files are **NOT** intended to be depended on by any code, such as tests or These files are **NOT** intended to be depended on by any code, such as tests or
or compiled examples. or compiled examples.

View File

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

View File

@@ -13,7 +13,7 @@ public struct Galaxy : IFlatbufferObject
{ {
private Table __p; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } 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) { return GetRootAsGalaxy(_bb, new Galaxy()); }
public static Galaxy GetRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } 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); } 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; private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } } 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) { 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 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); } 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 from pathlib import Path
import sys
# Get the path where this script is located so we can invoke the script from # Get the path where this script is located so we can invoke the script from
# any directory and have the paths work correctly. # any directory and have the paths work correctly.

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Galaxy extends Table { 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) { 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 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); } public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }

View File

@@ -21,7 +21,7 @@ import java.nio.ByteOrder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Universe extends Table { 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) { 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 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); } 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 return if(o != 0) bb.getLong(o + bb_pos) else 0L
} }
companion object { 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): Galaxy = getRootAsGalaxy(_bb, Galaxy())
fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy { fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy {
_bb.order(ByteOrder.LITTLE_ENDIAN) _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 val o = __offset(6); return if (o != 0) __vector_len(o) else 0
} }
companion object { 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): Universe = getRootAsUniverse(_bb, Universe())
fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe { fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe {
_bb.order(ByteOrder.LITTLE_ENDIAN) _bb.order(ByteOrder.LITTLE_ENDIAN)

View File

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

View File

@@ -2,11 +2,15 @@
// swiftlint:disable all // swiftlint:disable all
// swiftformat:disable all // swiftformat:disable all
#if canImport(Common)
import Common
#endif
import FlatBuffers import FlatBuffers
public struct flatbuffers_goldens_Galaxy: FlatBufferObject, Verifiable { 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 } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table
@@ -41,7 +45,7 @@ public struct flatbuffers_goldens_Galaxy: FlatBufferObject, Verifiable {
public struct flatbuffers_goldens_Universe: 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 } public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table private var _accessor: Table

View File

@@ -2,5 +2,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
export { Galaxy } from './galaxy.js'; export {Galaxy} from './galaxy.js';
export { Universe } from './universe.js'; export {Universe} from './universe.js';

View File

@@ -1,5 +1,4 @@
GRPC implementation and test GRPC implementation and test
============================
NOTE: files in `src/` are shared with the GRPC project, and maintained there 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 (any changes should be submitted to GRPC instead). These files are copied
@@ -40,3 +39,63 @@ For Bazel users:
```shell ```shell
$bazel test tests/... $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 argparse
import sys
import grpc import grpc
sys.path.insert(0, '../../../../../flatbuffers/python') sys.path.insert(0, "../../../../../flatbuffers/python")
import flatbuffers import flatbuffers
from models import HelloReply, HelloRequest, greeter_grpc_fb from models import HelloReply, HelloRequest, greeter_grpc_fb
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("port", help="server port to connect to", default=3000) 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): def say_hello(stub, hello_request):
reply = stub.SayHello(hello_request) reply = stub.SayHello(hello_request)
r = HelloReply.HelloReply.GetRootAs(reply) r = HelloReply.HelloReply.GetRootAs(reply)
print(r.Message()) print(r.Message())
def say_many_hellos(stub, hello_request): def say_many_hellos(stub, hello_request):
greetings = stub.SayManyHellos(hello_request) greetings = stub.SayManyHellos(hello_request)
for greeting in greetings: for greeting in greetings:
r = HelloReply.HelloReply.GetRootAs(greeting) r = HelloReply.HelloReply.GetRootAs(greeting)
print(r.Message()) print(r.Message())
def main(): def main():
args = parser.parse_args() 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() builder = flatbuffers.Builder()
ind = builder.CreateString(args.name) ind = builder.CreateString(args.name)
HelloRequest.HelloRequestStart(builder) HelloRequest.HelloRequestStart(builder)
@@ -37,4 +42,5 @@ def main():
say_hello(stub, output) say_hello(stub, output)
say_many_hellos(stub, output) say_many_hellos(stub, output)
main() main()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,21 @@
import * as grpc from '@grpc/grpc-js'; import * as grpc from '@grpc/grpc-js';
import * as flatbuffers from 'flatbuffers'; import * as flatbuffers from 'flatbuffers';
import { HelloReply } from './models/hello-reply'; import {GreeterClient} from './greeter_grpc';
import { HelloRequest } from './models/hello-request'; import {HelloReply} from './models/hello-reply';
import { GreeterClient } from './greeter_grpc'; import {HelloRequest} from './models/hello-request';
async function main(PORT: Number, name: string) { 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 builder = new flatbuffers.Builder();
const offset = builder.createString(name); const offset = builder.createString(name);
const root = HelloRequest.createHelloRequest(builder, offset); const root = HelloRequest.createHelloRequest(builder, offset);
builder.finish(root); 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) => { client.SayHello(buffer, (err, response) => {
console.log(response.message()); 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 PORT = Number(args[0]);
const name: string = args[1] ?? "flatbuffers"; const name: string = args[1] ?? 'flatbuffers';
if (PORT) { if (PORT) {
main(PORT, name); main(PORT, name);
} else { } else {
throw new Error("Requires a valid port number.") throw new Error('Requires a valid port number.');
} }

View File

@@ -1,4 +1,4 @@
// automatically generated by the FlatBuffers compiler, do not modify // automatically generated by the FlatBuffers compiler, do not modify
export { HelloReply } from './models/hello-reply.js'; export {HelloReply} from './models/hello-reply.js';
export { HelloRequest } from './models/hello-request.js'; export {HelloRequest} from './models/hello-request.js';

View File

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

View File

@@ -19,28 +19,29 @@ import com.google.flatbuffers.Table;
import io.grpc.Drainable; import io.grpc.Drainable;
import io.grpc.KnownLength; import io.grpc.KnownLength;
import io.grpc.MethodDescriptor; import io.grpc.MethodDescriptor;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import javax.annotation.Nullable;
public class FlatbuffersUtils { 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 { T extract(InputStream stream) throws IOException {
if (stream instanceof KnownLength) { if (stream instanceof KnownLength) {
int size = stream.available(); int size = stream.available();
ByteBuffer buffer = ByteBuffer.allocate(size); ByteBuffer buffer = ByteBuffer.allocate(size);
stream.read(buffer.array()); stream.read(buffer.array());
return extract(buffer); return extract(buffer);
} else } 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); public abstract T extract(ByteBuffer buffer);
} }
static class FBInputStream extends InputStream implements Drainable, KnownLength { static class FBInputStream extends InputStream implements Drainable, KnownLength {
@@ -81,18 +82,17 @@ public class FlatbuffersUtils {
makeStreamIfNotAlready(); makeStreamIfNotAlready();
return inputStream.read(b, off, len); return inputStream.read(b, off, len);
} }
} else } else return inputStream.read(b, off, len);
return inputStream.read(b, off, len);
} }
@Override @Override
public int available() throws IOException { public int available() throws IOException {
return inputStream == null ? size : inputStream.available(); 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>() { return new MethodDescriptor.ReflectableMarshaller<T>() {
@Override @Override
public Class<T> getMessageClass() { public Class<T> getMessageClass() {
@@ -101,7 +101,7 @@ public class FlatbuffersUtils {
@Override @Override
public InputStream stream(T value) { public InputStream stream(T value) {
return new FBInputStream (value.getByteBuffer()); return new FBInputStream(value.getByteBuffer());
} }
@Override @Override

File diff suppressed because it is too large Load Diff

View File

@@ -11,8 +11,8 @@
#include "src/compiler/schema_interface.h" #include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING #ifndef GRPC_CUSTOM_STRING
# include <string> #include <string>
# define GRPC_CUSTOM_STRING std::string #define GRPC_CUSTOM_STRING std::string
#endif #endif
namespace grpc { namespace grpc {
@@ -37,71 +37,73 @@ struct Parameters {
std::string message_header_extension; std::string message_header_extension;
// Default: ".grpc.fb.h" // Default: ".grpc.fb.h"
std::string service_header_extension; 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. // Return the prologue of the generated header file.
grpc::string GetHeaderPrologue(grpc_generator::File *file, grpc::string GetHeaderPrologue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the includes needed for generated header file. // Return the includes needed for generated header file.
grpc::string GetHeaderIncludes(grpc_generator::File *file, grpc::string GetHeaderIncludes(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the includes needed for generated source file. // Return the includes needed for generated source file.
grpc::string GetSourceIncludes(grpc_generator::File *file, grpc::string GetSourceIncludes(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the epilogue of the generated header file. // Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(grpc_generator::File *file, grpc::string GetHeaderEpilogue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the prologue of the generated source file. // Return the prologue of the generated source file.
grpc::string GetSourcePrologue(grpc_generator::File *file, grpc::string GetSourcePrologue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the services for generated header file. // Return the services for generated header file.
grpc::string GetHeaderServices(grpc_generator::File *file, grpc::string GetHeaderServices(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the services for generated source file. // Return the services for generated source file.
grpc::string GetSourceServices(grpc_generator::File *file, grpc::string GetSourceServices(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the epilogue of the generated source file. // Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(grpc_generator::File *file, grpc::string GetSourceEpilogue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the prologue of the generated mock file. // Return the prologue of the generated mock file.
grpc::string GetMockPrologue(grpc_generator::File *file, grpc::string GetMockPrologue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the includes needed for generated mock file. // Return the includes needed for generated mock file.
grpc::string GetMockIncludes(grpc_generator::File *file, grpc::string GetMockIncludes(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the services for generated mock file. // Return the services for generated mock file.
grpc::string GetMockServices(grpc_generator::File *file, grpc::string GetMockServices(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the epilogue of generated mock file. // Return the epilogue of generated mock file.
grpc::string GetMockEpilogue(grpc_generator::File *file, grpc::string GetMockEpilogue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the prologue of the generated mock file. // Return the prologue of the generated mock file.
grpc::string GetMockPrologue(grpc_generator::File *file, grpc::string GetMockPrologue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the includes needed for generated mock file. // Return the includes needed for generated mock file.
grpc::string GetMockIncludes(grpc_generator::File *file, grpc::string GetMockIncludes(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the services for generated mock file. // Return the services for generated mock file.
grpc::string GetMockServices(grpc_generator::File *file, grpc::string GetMockServices(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
// Return the epilogue of generated mock file. // Return the epilogue of generated mock file.
grpc::string GetMockEpilogue(grpc_generator::File *file, grpc::string GetMockEpilogue(grpc_generator::File* file,
const Parameters &params); const Parameters& params);
} // namespace grpc_cpp_generator } // namespace grpc_cpp_generator

View File

@@ -4,17 +4,18 @@
#include <map> #include <map>
#include <sstream> #include <sstream>
template<class T> grpc::string as_string(T x) { template <class T>
grpc::string as_string(T x) {
std::ostringstream out; std::ostringstream out;
out << x; out << x;
return out.str(); return out.str();
} }
inline bool ClientOnlyStreaming(const grpc_generator::Method *method) { inline bool ClientOnlyStreaming(const grpc_generator::Method* method) {
return method->ClientStreaming() && !method->ServerStreaming(); return method->ClientStreaming() && !method->ServerStreaming();
} }
inline bool ServerOnlyStreaming(const grpc_generator::Method *method) { inline bool ServerOnlyStreaming(const grpc_generator::Method* method) {
return !method->ClientStreaming() && method->ServerStreaming(); return !method->ClientStreaming() && method->ServerStreaming();
} }
@@ -35,7 +36,7 @@ static grpc::string exportName(grpc::string s) {
return s; return s;
} }
static void GenerateError(grpc_generator::Printer *printer, static void GenerateError(grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars, std::map<grpc::string, grpc::string> vars,
const bool multiple_return = true) { const bool multiple_return = true) {
printer->Print(vars, "if $Error_Check$ {\n"); printer->Print(vars, "if $Error_Check$ {\n");
@@ -47,8 +48,8 @@ static void GenerateError(grpc_generator::Printer *printer,
} }
// Generates imports for the service // Generates imports for the service
static void GenerateImports(grpc_generator::File *file, static void GenerateImports(grpc_generator::File* file,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
vars["filename"] = file->filename(); vars["filename"] = file->filename();
printer->Print("//Generated by gRPC Go plugin\n"); printer->Print("//Generated by gRPC Go plugin\n");
@@ -67,8 +68,8 @@ static void GenerateImports(grpc_generator::File *file,
} }
// Generates Server method signature source // Generates Server method signature source
static void GenerateServerMethodSignature(const grpc_generator::Method *method, static void GenerateServerMethodSignature(
grpc_generator::Printer *printer, const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name()); vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name(); vars["Request"] = method->get_input_type_name();
@@ -87,8 +88,8 @@ static void GenerateServerMethodSignature(const grpc_generator::Method *method,
} }
} }
static void GenerateServerMethod(const grpc_generator::Method *method, static void GenerateServerMethod(const grpc_generator::Method* method,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name()); vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_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->Print(vars, "type $Service$_$Method$Server interface {\n");
printer->Indent(); printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Response$) error\n"); } if (genSend) {
if (genRecv) { printer->Print(vars, "Recv() (*$Request$, error)\n"); } printer->Print(vars, "Send(*$Response$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Request$, error)\n");
}
if (genSendAndClose) { if (genSendAndClose) {
printer->Print(vars, "SendAndClose(*$Response$) error\n"); printer->Print(vars, "SendAndClose(*$Response$) error\n");
} }
@@ -205,8 +210,8 @@ static void GenerateServerMethod(const grpc_generator::Method *method,
} }
// Generates Client method signature source // Generates Client method signature source
static void GenerateClientMethodSignature(const grpc_generator::Method *method, static void GenerateClientMethodSignature(
grpc_generator::Printer *printer, const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name()); vars["Method"] = exportName(method->name());
vars["Request"] = vars["Request"] =
@@ -226,8 +231,8 @@ static void GenerateClientMethodSignature(const grpc_generator::Method *method,
} }
// Generates Client method source // Generates Client method source
static void GenerateClientMethod(const grpc_generator::Method *method, static void GenerateClientMethod(const grpc_generator::Method* method,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
printer->Print(vars, "func (c *$ServiceUnexported$Client) "); printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
vars["Ending"] = " {\n"; vars["Ending"] = " {\n";
@@ -277,8 +282,12 @@ static void GenerateClientMethod(const grpc_generator::Method *method,
// Stream interface // Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n"); printer->Print(vars, "type $Service$_$Method$Client interface {\n");
printer->Indent(); printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Request$) error\n"); } if (genSend) {
if (genRecv) { printer->Print(vars, "Recv() (*$Response$, error)\n"); } printer->Print(vars, "Send(*$Request$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Response$, error)\n");
}
if (genCloseAndRecv) { if (genCloseAndRecv) {
printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n"); printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
} }
@@ -329,8 +338,8 @@ static void GenerateClientMethod(const grpc_generator::Method *method,
} }
// Generates client API for the service // Generates client API for the service
void GenerateService(const grpc_generator::Service *service, void GenerateService(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) { std::map<grpc::string, grpc::string> vars) {
vars["Service"] = exportName(service->name()); vars["Service"] = exportName(service->name());
// Client Interface // Client Interface
@@ -484,9 +493,9 @@ void GenerateService(const grpc_generator::Service *service,
} // namespace } // namespace
// Returns source for the service // Returns source for the service
grpc::string GenerateServiceSource(grpc_generator::File *file, grpc::string GenerateServiceSource(grpc_generator::File* file,
const grpc_generator::Service *service, const grpc_generator::Service* service,
grpc_go_generator::Parameters *parameters) { grpc_go_generator::Parameters* parameters) {
grpc::string out; grpc::string out;
auto p = file->CreatePrinter(&out, '\t'); auto p = file->CreatePrinter(&out, '\t');
p->SetIndentationSize(1); p->SetIndentationSize(1);

View File

@@ -24,9 +24,9 @@ struct Parameters {
}; };
// Return the source of the generated service file. // Return the source of the generated service file.
grpc::string GenerateServiceSource(grpc_generator::File *file, grpc::string GenerateServiceSource(grpc_generator::File* file,
const grpc_generator::Service *service, const grpc_generator::Service* service,
grpc_go_generator::Parameters *parameters); grpc_go_generator::Parameters* parameters);
} // namespace grpc_go_generator } // namespace grpc_go_generator

View File

@@ -28,11 +28,11 @@
// Stringify helpers used solely to cast GRPC_VERSION // Stringify helpers used solely to cast GRPC_VERSION
#ifndef STR #ifndef STR
# define STR(s) # s #define STR(s) #s
#endif #endif
#ifndef XSTR #ifndef XSTR
# define XSTR(s) STR(s) #define XSTR(s) STR(s)
#endif #endif
typedef grpc_generator::Printer Printer; typedef grpc_generator::Printer Printer;
@@ -46,8 +46,8 @@ namespace grpc_java_generator {
typedef std::string string; typedef std::string string;
namespace { namespace {
// Generates imports for the service // Generates imports for the service
static void GenerateImports(grpc_generator::File *file, static void GenerateImports(grpc_generator::File* file,
grpc_generator::Printer *printer, VARS &vars) { grpc_generator::Printer* printer, VARS& vars) {
vars["filename"] = file->filename(); vars["filename"] = file->filename();
printer->Print(vars, printer->Print(vars,
"//Generated by flatc compiler (version $flatc_version$)\n"); "//Generated by flatc compiler (version $flatc_version$)\n");
@@ -64,7 +64,7 @@ static void GenerateImports(grpc_generator::File *file,
// Adjust a method name prefix identifier to follow the JavaBean spec: // Adjust a method name prefix identifier to follow the JavaBean spec:
// - decapitalize the first letter // - decapitalize the first letter
// - remove embedded underscores & capitalize the following letter // - remove embedded underscores & capitalize the following letter
static string MixedLower(const string &word) { static string MixedLower(const string& word) {
string w; string w;
w += static_cast<string::value_type>(tolower(word[0])); w += static_cast<string::value_type>(tolower(word[0]));
bool after_underscore = false; bool after_underscore = false;
@@ -84,7 +84,7 @@ static string MixedLower(const string &word) {
// - An underscore is inserted where a lower case letter is followed by an // - An underscore is inserted where a lower case letter is followed by an
// upper case letter. // upper case letter.
// - All letters are converted to upper case // - All letters are converted to upper case
static string ToAllUpperCase(const string &word) { static string ToAllUpperCase(const string& word) {
string w; string w;
for (size_t i = 0; i < word.length(); ++i) { for (size_t i = 0; i < word.length(); ++i) {
w += static_cast<string::value_type>(toupper(word[i])); w += static_cast<string::value_type>(toupper(word[i]));
@@ -95,49 +95,48 @@ static string ToAllUpperCase(const string &word) {
return w; return w;
} }
static inline string LowerMethodName(const MethodDescriptor *method) { static inline string LowerMethodName(const MethodDescriptor* method) {
return MixedLower(method->name()); return MixedLower(method->name());
} }
static inline string MethodPropertiesFieldName(const MethodDescriptor *method) { static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
return "METHOD_" + ToAllUpperCase(method->name()); return "METHOD_" + ToAllUpperCase(method->name());
} }
static inline string MethodPropertiesGetterName( static inline string MethodPropertiesGetterName(
const MethodDescriptor *method) { const MethodDescriptor* method) {
return MixedLower("get_" + method->name() + "_method"); return MixedLower("get_" + method->name() + "_method");
} }
static inline string MethodIdFieldName(const MethodDescriptor *method) { static inline string MethodIdFieldName(const MethodDescriptor* method) {
return "METHODID_" + ToAllUpperCase(method->name()); return "METHODID_" + ToAllUpperCase(method->name());
} }
static inline string JavaClassName(VARS &vars, const string &name) { static inline string JavaClassName(VARS& vars, const string& name) {
// string name = google::protobuf::compiler::java::ClassName(desc); // string name = google::protobuf::compiler::java::ClassName(desc);
return vars["Package"] + name; return vars["Package"] + name;
} }
static inline string ServiceClassName(const string &service_name) { static inline string ServiceClassName(const string& service_name) {
return service_name + "Grpc"; return service_name + "Grpc";
} }
// TODO(nmittler): Remove once protobuf includes javadoc methods in // TODO(nmittler): Remove once protobuf includes javadoc methods in
// distribution. // distribution.
template<typename ITR> template <typename ITR>
static void GrpcSplitStringToIteratorUsing(const string &full, static void GrpcSplitStringToIteratorUsing(const string& full,
const char *delim, ITR &result) { const char* delim, ITR& result) {
// Optimize the common case where delim is a single character. // Optimize the common case where delim is a single character.
if (delim[0] != '\0' && delim[1] == '\0') { if (delim[0] != '\0' && delim[1] == '\0') {
char c = delim[0]; char c = delim[0];
const char *p = full.data(); const char* p = full.data();
const char *end = p + full.size(); const char* end = p + full.size();
while (p != end) { while (p != end) {
if (*p == c) { if (*p == c) {
++p; ++p;
} else { } else {
const char *start = p; const char* start = p;
while (++p != end && *p != c) while (++p != end && *p != c);
;
*result++ = string(start, p - start); *result++ = string(start, p - start);
} }
} }
@@ -157,13 +156,13 @@ static void GrpcSplitStringToIteratorUsing(const string &full,
} }
} }
static void GrpcSplitStringUsing(const string &full, const char *delim, static void GrpcSplitStringUsing(const string& full, const char* delim,
std::vector<string> *result) { std::vector<string>* result) {
std::back_insert_iterator<std::vector<string>> it(*result); std::back_insert_iterator<std::vector<string>> it(*result);
GrpcSplitStringToIteratorUsing(full, delim, it); GrpcSplitStringToIteratorUsing(full, delim, it);
} }
static std::vector<string> GrpcSplit(const string &full, const char *delim) { static std::vector<string> GrpcSplit(const string& full, const char* delim) {
std::vector<string> result; std::vector<string> result;
GrpcSplitStringUsing(full, delim, &result); GrpcSplitStringUsing(full, delim, &result);
return result; return result;
@@ -171,7 +170,7 @@ static std::vector<string> GrpcSplit(const string &full, const char *delim) {
// TODO(nmittler): Remove once protobuf includes javadoc methods in // TODO(nmittler): Remove once protobuf includes javadoc methods in
// distribution. // distribution.
static string GrpcEscapeJavadoc(const string &input) { static string GrpcEscapeJavadoc(const string& input) {
string result; string result;
result.reserve(input.size() * 2); result.reserve(input.size() * 2);
@@ -218,7 +217,9 @@ static string GrpcEscapeJavadoc(const string &input) {
// Java interprets Unicode escape sequences anywhere! // Java interprets Unicode escape sequences anywhere!
result.append("&#92;"); result.append("&#92;");
break; break;
default: result.push_back(c); break; default:
result.push_back(c);
break;
} }
prev = c; prev = c;
@@ -227,7 +228,7 @@ static string GrpcEscapeJavadoc(const string &input) {
return result; return result;
} }
static std::vector<string> GrpcGetDocLines(const string &comments) { static std::vector<string> GrpcGetDocLines(const string& comments) {
if (!comments.empty()) { if (!comments.empty()) {
// TODO(kenton): Ideally we should parse the comment text as Markdown and // TODO(kenton): Ideally we should parse the comment text as Markdown and
// write it back as HTML, but this requires a Markdown parser. For now // write it back as HTML, but this requires a Markdown parser. For now
@@ -238,23 +239,27 @@ static std::vector<string> GrpcGetDocLines(const string &comments) {
string escapedComments = GrpcEscapeJavadoc(comments); string escapedComments = GrpcEscapeJavadoc(comments);
std::vector<string> lines = GrpcSplit(escapedComments, "\n"); 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 lines;
} }
return std::vector<string>(); return std::vector<string>();
} }
static std::vector<string> GrpcGetDocLinesForDescriptor( static std::vector<string> GrpcGetDocLinesForDescriptor(
const DescriptorType *descriptor) { const DescriptorType* descriptor) {
return descriptor->GetAllComments(); return descriptor->GetAllComments();
// return GrpcGetDocLines(descriptor->GetLeadingComments("///")); // return GrpcGetDocLines(descriptor->GetLeadingComments("///"));
} }
static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars, static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
const std::vector<string> &lines, const std::vector<string>& lines,
bool surroundWithPreTag) { bool surroundWithPreTag) {
if (!lines.empty()) { if (!lines.empty()) {
if (surroundWithPreTag) { printer->Print(" * <pre>\n"); } if (surroundWithPreTag) {
printer->Print(" * <pre>\n");
}
for (size_t i = 0; i < lines.size(); i++) { for (size_t i = 0; i < lines.size(); i++) {
// Most lines should start with a space. Watch out for lines that start // Most lines should start with a space. Watch out for lines that start
@@ -268,28 +273,30 @@ static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
} }
} }
if (surroundWithPreTag) { printer->Print(" * </pre>\n"); } if (surroundWithPreTag) {
printer->Print(" * </pre>\n");
}
} }
} }
static void GrpcWriteDocComment(Printer *printer, VARS &vars, static void GrpcWriteDocComment(Printer* printer, VARS& vars,
const string &comments) { const string& comments) {
printer->Print("/**\n"); printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLines(comments); std::vector<string> lines = GrpcGetDocLines(comments);
GrpcWriteDocCommentBody(printer, vars, lines, false); GrpcWriteDocCommentBody(printer, vars, lines, false);
printer->Print(" */\n"); printer->Print(" */\n");
} }
static void GrpcWriteServiceDocComment(Printer *printer, VARS &vars, static void GrpcWriteServiceDocComment(Printer* printer, VARS& vars,
const ServiceDescriptor *service) { const ServiceDescriptor* service) {
printer->Print("/**\n"); printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(service); std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
GrpcWriteDocCommentBody(printer, vars, lines, true); GrpcWriteDocCommentBody(printer, vars, lines, true);
printer->Print(" */\n"); printer->Print(" */\n");
} }
static void GrpcWriteMethodDocComment(Printer *printer, VARS &vars, static void GrpcWriteMethodDocComment(Printer* printer, VARS& vars,
const MethodDescriptor *method) { const MethodDescriptor* method) {
printer->Print("/**\n"); printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(method); std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
GrpcWriteDocCommentBody(printer, vars, lines, true); GrpcWriteDocCommentBody(printer, vars, lines, true);
@@ -298,7 +305,7 @@ static void GrpcWriteMethodDocComment(Printer *printer, VARS &vars,
// outputs static singleton extractor for type stored in "extr_type" and // outputs static singleton extractor for type stored in "extr_type" and
// "extr_type_name" vars // "extr_type_name" vars
static void PrintTypeExtractor(Printer *p, VARS &vars) { static void PrintTypeExtractor(Printer* p, VARS& vars) {
p->Print(vars, p->Print(vars,
"private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> " "private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> "
"extractorOf$extr_type_name$;\n" "extractorOf$extr_type_name$;\n"
@@ -320,8 +327,8 @@ static void PrintTypeExtractor(Printer *p, VARS &vars) {
" }\n" " }\n"
"}\n\n"); "}\n\n");
} }
static void PrintMethodFields(Printer *p, VARS &vars, static void PrintMethodFields(Printer* p, VARS& vars,
const ServiceDescriptor *service) { const ServiceDescriptor* service) {
p->Print("// Static method descriptors that strictly reflect the proto.\n"); p->Print("// Static method descriptors that strictly reflect the proto.\n");
vars["service_name"] = service->name(); vars["service_name"] = service->name();
@@ -443,11 +450,11 @@ enum StubType {
enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 }; enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 };
static void PrintBindServiceMethodBody(Printer *p, VARS &vars, static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
const ServiceDescriptor *service); const ServiceDescriptor* service);
// Prints a client interface or implementation class, or a server interface. // Prints a client interface or implementation class, or a server interface.
static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
StubType type) { StubType type) {
const string service_name = service->name(); const string service_name = service->name();
vars["service_name"] = service_name; vars["service_name"] = service_name;
@@ -493,7 +500,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
vars["client_name"] = client_name; vars["client_name"] = client_name;
// Class head // Class head
if (!interface) { GrpcWriteServiceDocComment(p, vars, service); } if (!interface) {
GrpcWriteServiceDocComment(p, vars, service);
}
if (impl_base) { if (impl_base) {
p->Print(vars, p->Print(vars,
"public static abstract class $abstract_name$ implements " "public static abstract class $abstract_name$ implements "
@@ -555,7 +564,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
p->Print("\n"); p->Print("\n");
// TODO(nmittler): Replace with WriteMethodDocComment once included by the // TODO(nmittler): Replace with WriteMethodDocComment once included by the
// protobuf distro. // protobuf distro.
if (!interface) { GrpcWriteMethodDocComment(p, vars, &*method); } if (!interface) {
GrpcWriteMethodDocComment(p, vars, &*method);
}
p->Print("public "); p->Print("public ");
switch (call_type) { switch (call_type) {
case BLOCKING_CALL: case BLOCKING_CALL:
@@ -620,7 +631,8 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
"responseObserver);\n"); "responseObserver);\n");
} }
break; break;
default: break; default:
break;
} }
} else if (!interface) { } else if (!interface) {
switch (call_type) { switch (call_type) {
@@ -695,15 +707,15 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
} }
static bool CompareMethodClientStreaming( static bool CompareMethodClientStreaming(
const std::unique_ptr<const grpc_generator::Method> &method1, const std::unique_ptr<const grpc_generator::Method>& method1,
const std::unique_ptr<const grpc_generator::Method> &method2) { const std::unique_ptr<const grpc_generator::Method>& method2) {
return method1->ClientStreaming() < method2->ClientStreaming(); return method1->ClientStreaming() < method2->ClientStreaming();
} }
// Place all method invocations into a single class to reduce memory footprint // Place all method invocations into a single class to reduce memory footprint
// on Android. // on Android.
static void PrintMethodHandlerClass(Printer *p, VARS &vars, static void PrintMethodHandlerClass(Printer* p, VARS& vars,
const ServiceDescriptor *service) { const ServiceDescriptor* service) {
// Sort method ids based on ClientStreaming() so switch tables are compact. // Sort method ids based on ClientStreaming() so switch tables are compact.
std::vector<std::unique_ptr<const grpc_generator::Method>> sorted_methods( std::vector<std::unique_ptr<const grpc_generator::Method>> sorted_methods(
service->method_count()); service->method_count());
@@ -713,7 +725,7 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars,
stable_sort(sorted_methods.begin(), sorted_methods.end(), stable_sort(sorted_methods.begin(), sorted_methods.end(),
CompareMethodClientStreaming); CompareMethodClientStreaming);
for (size_t i = 0; i < sorted_methods.size(); i++) { for (size_t i = 0; i < sorted_methods.size(); i++) {
auto &method = sorted_methods[i]; auto& method = sorted_methods[i];
vars["method_id"] = to_string(i); vars["method_id"] = to_string(i);
vars["method_id_name"] = MethodIdFieldName(&*method); vars["method_id_name"] = MethodIdFieldName(&*method);
p->Print(vars, p->Print(vars,
@@ -746,7 +758,9 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars,
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(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["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method); vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); 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) { for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(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["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method); vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
@@ -803,8 +819,8 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars,
p->Print("}\n\n"); p->Print("}\n\n");
} }
static void PrintGetServiceDescriptorMethod(Printer *p, VARS &vars, static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
const ServiceDescriptor *service) { const ServiceDescriptor* service) {
vars["service_name"] = service->name(); vars["service_name"] = service->name();
// vars["proto_base_descriptor_supplier"] = service->name() + // vars["proto_base_descriptor_supplier"] = service->name() +
// "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] = // "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] =
@@ -896,8 +912,8 @@ static void PrintGetServiceDescriptorMethod(Printer *p, VARS &vars,
p->Print("}\n"); p->Print("}\n");
} }
static void PrintBindServiceMethodBody(Printer *p, VARS &vars, static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
const ServiceDescriptor *service) { const ServiceDescriptor* service) {
vars["service_name"] = service->name(); vars["service_name"] = service->name();
p->Indent(); p->Indent();
p->Print(vars, p->Print(vars,
@@ -949,8 +965,8 @@ static void PrintBindServiceMethodBody(Printer *p, VARS &vars,
p->Outdent(); p->Outdent();
} }
static void PrintService(Printer *p, VARS &vars, static void PrintService(Printer* p, VARS& vars,
const ServiceDescriptor *service, const ServiceDescriptor* service,
bool disable_version) { bool disable_version) {
vars["service_name"] = service->name(); vars["service_name"] = service->name();
vars["service_class_name"] = ServiceClassName(service->name()); vars["service_class_name"] = ServiceClassName(service->name());
@@ -1030,7 +1046,7 @@ static void PrintService(Printer *p, VARS &vars,
p->Print("}\n"); p->Print("}\n");
} }
static void PrintStaticImports(Printer *p) { static void PrintStaticImports(Printer* p) {
p->Print( p->Print(
"import java.nio.ByteBuffer;\n" "import java.nio.ByteBuffer;\n"
"import static " "import static "
@@ -1063,8 +1079,8 @@ static void PrintStaticImports(Printer *p) {
"io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n"); "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n");
} }
static void GenerateService(const grpc_generator::Service *service, static void GenerateService(const grpc_generator::Service* service,
grpc_generator::Printer *printer, VARS &vars, grpc_generator::Printer* printer, VARS& vars,
bool disable_version) { bool disable_version) {
// All non-generated classes must be referred by fully qualified names to // All non-generated classes must be referred by fully qualified names to
// avoid collision with generated classes. // avoid collision with generated classes.
@@ -1101,8 +1117,8 @@ static void GenerateService(const grpc_generator::Service *service,
} // namespace } // namespace
grpc::string GenerateServiceSource( grpc::string GenerateServiceSource(
grpc_generator::File *file, const grpc_generator::Service *service, grpc_generator::File* file, const grpc_generator::Service* service,
grpc_java_generator::Parameters *parameters) { grpc_java_generator::Parameters* parameters) {
grpc::string out; grpc::string out;
auto printer = file->CreatePrinter(&out); auto printer = file->CreatePrinter(&out);
VARS vars; VARS vars;

View File

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

View File

@@ -35,20 +35,22 @@ namespace flatbuffers {
namespace python { namespace python {
namespace grpc { namespace grpc {
namespace { namespace {
bool ClientStreaming(const RPCCall *method) { bool ClientStreaming(const RPCCall* method) {
const Value *val = method->attributes.Lookup("streaming"); 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) { bool ServerStreaming(const RPCCall* method) {
const Value *val = method->attributes.Lookup("streaming"); 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) { void FormatImports(std::stringstream& ss, const Imports& imports) {
std::set<std::string> modules; std::set<std::string> modules;
std::map<std::string, std::set<std::string>> names_by_module; std::map<std::string, std::set<std::string>> names_by_module;
for (const Import &import : imports.imports) { for (const Import& import : imports.imports) {
if (import.IsLocal()) continue; // skip all local imports if (import.IsLocal()) continue; // skip all local imports
if (import.name == "") { if (import.name == "") {
modules.insert(import.module); modules.insert(import.module);
@@ -57,14 +59,14 @@ void FormatImports(std::stringstream &ss, const Imports &imports) {
} }
} }
for (const std::string &module : modules) { for (const std::string& module : modules) {
ss << "import " << module << '\n'; ss << "import " << module << '\n';
} }
ss << '\n'; ss << '\n';
for (const auto &import : names_by_module) { for (const auto& import : names_by_module) {
ss << "from " << import.first << " import "; ss << "from " << import.first << " import ";
size_t i = 0; size_t i = 0;
for (const std::string &name : import.second) { for (const std::string& name : import.second) {
if (i > 0) ss << ", "; if (i > 0) ss << ", ";
ss << name; ss << name;
++i; ++i;
@@ -74,8 +76,8 @@ void FormatImports(std::stringstream &ss, const Imports &imports) {
ss << "\n\n"; ss << "\n\n";
} }
bool SaveStub(const std::string &filename, const Imports &imports, bool SaveStub(const std::string& filename, const Imports& imports,
const std::string &content) { const std::string& content) {
std::stringstream ss; std::stringstream ss;
ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n" ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n"
<< '\n' << '\n'
@@ -88,8 +90,8 @@ bool SaveStub(const std::string &filename, const Imports &imports,
return flatbuffers::SaveFile(filename.c_str(), ss.str(), false); return flatbuffers::SaveFile(filename.c_str(), ss.str(), false);
} }
bool SaveService(const std::string &filename, const Imports &imports, bool SaveService(const std::string& filename, const Imports& imports,
const std::string &content) { const std::string& content) {
std::stringstream ss; std::stringstream ss;
ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n" << '\n'; ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n" << '\n';
FormatImports(ss, imports); FormatImports(ss, imports);
@@ -101,14 +103,15 @@ bool SaveService(const std::string &filename, const Imports &imports,
class BaseGenerator { class BaseGenerator {
protected: protected:
BaseGenerator(const Parser &parser, const Namer::Config &config, BaseGenerator(const Parser& parser, const Namer::Config& config,
const std::string &path, const Version &version) const std::string& path, const Version& version)
: parser_{parser}, : parser_{parser},
namer_{WithFlagOptions(config, parser.opts, path), Keywords(version)}, namer_{WithFlagOptions(config, parser.opts, path), Keywords(version)},
version_{version} {} version_{version},
path_(path) {}
protected: protected:
std::string ModuleForFile(const std::string &file) const { std::string ModuleForFile(const std::string& file) const {
std::string module = parser_.opts.include_prefix + StripExtension(file) + std::string module = parser_.opts.include_prefix + StripExtension(file) +
parser_.opts.filename_suffix; parser_.opts.filename_suffix;
std::replace(module.begin(), module.end(), '/', '.'); std::replace(module.begin(), module.end(), '/', '.');
@@ -116,46 +119,70 @@ class BaseGenerator {
} }
template <typename T> template <typename T>
std::string ModuleFor(const T *def) const { std::string ModuleFor(const T* def) const {
if (parser_.opts.one_file) return ModuleForFile(def->file); if (parser_.opts.one_file) return ModuleForFile(def->file);
return namer_.NamespacedType(*def); return namer_.NamespacedType(*def);
} }
const Parser &parser_; 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 IdlNamer namer_;
const Version version_; const Version version_;
const std::string& path_;
}; };
class StubGenerator : public BaseGenerator { class StubGenerator : public BaseGenerator {
public: public:
StubGenerator(const Parser &parser, const std::string &path, StubGenerator(const Parser& parser, const std::string& path,
const Version &version) const Version& version)
: BaseGenerator(parser, kStubConfig, path, version) {} : BaseGenerator(parser, kStubConfig, path, version) {}
bool Generate() { bool Generate() {
Imports imports; Imports imports;
std::stringstream stub; std::stringstream stub;
for (const ServiceDef *service : parser_.services_.vec) { std::string ns_name{};
for (const ServiceDef* service : parser_.services_.vec) {
Generate(stub, service, &imports); 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 = std::string filename =
namer_.config_.output_path + ns_name + kPathSeparator +
StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" + 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()); return SaveStub(filename, imports, stub.str());
} }
private: private:
void Generate(std::stringstream &ss, const ServiceDef *service, void Generate(std::stringstream& ss, const ServiceDef* service,
Imports *imports) { Imports* imports) {
imports->Import("grpc"); imports->Import("grpc");
ss << "class " << service->name << "Stub(object):\n" ss << "class " << service->name << "Stub(object):\n"
<< " def __init__(self, channel: grpc.Channel) -> None: ...\n"; << " def __init__(self, channel: grpc.Channel) -> None: ...\n";
for (const RPCCall *method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
std::string request = "bytes"; std::string request = "bytes";
std::string response = "bytes"; std::string response = "bytes";
@@ -187,7 +214,7 @@ class StubGenerator : public BaseGenerator {
ss << "\n\n"; ss << "\n\n";
ss << "class " << service->name << "Servicer(object):\n"; ss << "class " << service->name << "Servicer(object):\n";
for (const RPCCall *method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
std::string request = "bytes"; std::string request = "bytes";
std::string response = "bytes"; std::string response = "bytes";
@@ -226,8 +253,8 @@ class StubGenerator : public BaseGenerator {
class ServiceGenerator : public BaseGenerator { class ServiceGenerator : public BaseGenerator {
public: public:
ServiceGenerator(const Parser &parser, const std::string &path, ServiceGenerator(const Parser& parser, const std::string& path,
const Version &version) const Version& version)
: BaseGenerator(parser, kConfig, path, version) {} : BaseGenerator(parser, kConfig, path, version) {}
bool Generate() { bool Generate() {
@@ -247,23 +274,27 @@ class ServiceGenerator : public BaseGenerator {
<< '\n'; << '\n';
} }
for (const ServiceDef *service : parser_.services_.vec) { std::string ns_name{};
for (const ServiceDef* service : parser_.services_.vec) {
GenerateStub(ss, service, &imports); GenerateStub(ss, service, &imports);
GenerateServicer(ss, service, &imports); GenerateServicer(ss, service, &imports);
GenerateRegister(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 = std::string filename =
namer_.config_.output_path + ns_name + kPathSeparator +
StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" + 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()); return SaveService(filename, imports, ss.str());
} }
private: private:
void GenerateStub(std::stringstream &ss, const ServiceDef *service, void GenerateStub(std::stringstream& ss, const ServiceDef* service,
Imports *imports) { Imports* imports) {
ss << "class " << service->name << "Stub"; ss << "class " << service->name << "Stub";
if (version_.major != 3) ss << "(object)"; if (version_.major != 3) ss << "(object)";
ss << ":\n" ss << ":\n"
@@ -277,7 +308,7 @@ class ServiceGenerator : public BaseGenerator {
<< " '''\n" << " '''\n"
<< '\n'; << '\n';
for (const RPCCall *method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
std::string response = namer_.Type(*method->response); std::string response = namer_.Type(*method->response);
imports->Import(ModuleFor(method->response), response); imports->Import(ModuleFor(method->response), response);
@@ -300,8 +331,8 @@ class ServiceGenerator : public BaseGenerator {
ss << '\n'; ss << '\n';
} }
void GenerateServicer(std::stringstream &ss, const ServiceDef *service, void GenerateServicer(std::stringstream& ss, const ServiceDef* service,
Imports *imports) { Imports* imports) {
imports->Import("grpc"); imports->Import("grpc");
ss << "class " << service->name << "Servicer"; ss << "class " << service->name << "Servicer";
@@ -310,7 +341,7 @@ class ServiceGenerator : public BaseGenerator {
<< " '''Interface exported by the server.'''\n" << " '''Interface exported by the server.'''\n"
<< '\n'; << '\n';
for (const RPCCall *method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
const std::string request_param = const std::string request_param =
ClientStreaming(method) ? "request_iterator" : "request"; ClientStreaming(method) ? "request_iterator" : "request";
ss << " def " << method->name << "(self, " << request_param ss << " def " << method->name << "(self, " << request_param
@@ -324,15 +355,15 @@ class ServiceGenerator : public BaseGenerator {
ss << '\n'; ss << '\n';
} }
void GenerateRegister(std::stringstream &ss, const ServiceDef *service, void GenerateRegister(std::stringstream& ss, const ServiceDef* service,
Imports *imports) { Imports* imports) {
imports->Import("grpc"); imports->Import("grpc");
ss << "def add_" << service->name ss << "def add_" << service->name
<< "Servicer_to_server(servicer, server):\n" << "Servicer_to_server(servicer, server):\n"
<< " rpc_method_handlers = {\n"; << " rpc_method_handlers = {\n";
for (const RPCCall *method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
std::string request = namer_.Type(*method->request); std::string request = namer_.Type(*method->request);
imports->Import(ModuleFor(method->request), request); imports->Import(ModuleFor(method->request), request);
@@ -363,14 +394,14 @@ class ServiceGenerator : public BaseGenerator {
}; };
} // namespace } // namespace
bool Generate(const Parser &parser, const std::string &path, bool Generate(const Parser& parser, const std::string& path,
const Version &version) { const Version& version) {
ServiceGenerator generator{parser, path, version}; ServiceGenerator generator{parser, path, version};
return generator.Generate(); return generator.Generate();
} }
bool GenerateStub(const Parser &parser, const std::string &path, bool GenerateStub(const Parser& parser, const std::string& path,
const Version &version) { const Version& version) {
StubGenerator generator{parser, path, version}; StubGenerator generator{parser, path, version};
return generator.Generate(); return generator.Generate();
} }

View File

@@ -27,11 +27,11 @@
namespace flatbuffers { namespace flatbuffers {
namespace python { namespace python {
namespace grpc { namespace grpc {
bool Generate(const Parser &parser, const std::string &path, bool Generate(const Parser& parser, const std::string& path,
const Version &version); const Version& version);
bool GenerateStub(const Parser &parser, const std::string &path, bool GenerateStub(const Parser& parser, const std::string& path,
const Version &version); const Version& version);
} // namespace grpc } // namespace grpc
} // namespace python } // namespace python
} // namespace flatbuffers } // namespace flatbuffers

View File

@@ -24,8 +24,8 @@
#include <vector> #include <vector>
#ifndef GRPC_CUSTOM_STRING #ifndef GRPC_CUSTOM_STRING
# include <string> #include <string>
# define GRPC_CUSTOM_STRING std::string #define GRPC_CUSTOM_STRING std::string
#endif #endif
namespace grpc { namespace grpc {
@@ -55,10 +55,10 @@ struct Method : public CommentHolder {
virtual grpc::string output_type_name() const = 0; virtual grpc::string output_type_name() const = 0;
virtual bool get_module_and_message_path_input( virtual bool get_module_and_message_path_input(
grpc::string *str, grpc::string generator_file_name, grpc::string* str, grpc::string generator_file_name,
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
virtual bool get_module_and_message_path_output( virtual bool get_module_and_message_path_output(
grpc::string *str, grpc::string generator_file_name, grpc::string* str, grpc::string generator_file_name,
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
virtual std::vector<grpc::string> get_input_namespace_parts() const = 0; virtual std::vector<grpc::string> get_input_namespace_parts() const = 0;
@@ -89,9 +89,9 @@ struct Service : public CommentHolder {
struct Printer { struct Printer {
virtual ~Printer() {} virtual ~Printer() {}
virtual void Print(const std::map<grpc::string, grpc::string> &vars, virtual void Print(const std::map<grpc::string, grpc::string>& vars,
const char *template_string) = 0; const char* template_string) = 0;
virtual void Print(const char *string) = 0; virtual void Print(const char* string) = 0;
virtual void SetIndentationSize(const size_t size) = 0; virtual void SetIndentationSize(const size_t size) = 0;
virtual void Indent() = 0; virtual void Indent() = 0;
virtual void Outdent() = 0; virtual void Outdent() = 0;
@@ -112,7 +112,7 @@ struct File : public CommentHolder {
virtual std::unique_ptr<const Service> service(int i) const = 0; virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter( virtual std::unique_ptr<Printer> CreatePrinter(
grpc::string *str, const char indentation_type = ' ') const = 0; grpc::string* str, const char indentation_type = ' ') const = 0;
}; };
} // namespace grpc_generator } // namespace grpc_generator

View File

@@ -20,34 +20,35 @@
* please open an issue in the flatbuffers repository. This file should always * please open an issue in the flatbuffers repository. This file should always
* be maintained according to the Swift-grpc repository * be maintained according to the Swift-grpc repository
*/ */
#include "src/compiler/swift_generator.h"
#include <map> #include <map>
#include <sstream> #include <sstream>
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include "src/compiler/schema_interface.h" #include "src/compiler/schema_interface.h"
#include "src/compiler/swift_generator.h"
namespace grpc_swift_generator { namespace grpc_swift_generator {
namespace { namespace {
static std::string WrapInNameSpace(const std::vector<std::string> &components, static std::string WrapInNameSpace(const std::vector<std::string>& components,
const grpc::string &name) { const grpc::string& name) {
std::string qualified_name; std::string qualified_name;
for (auto it = components.begin(); it != components.end(); ++it) for (auto it = components.begin(); it != components.end(); ++it)
qualified_name += *it + "_"; qualified_name += *it + "_";
return qualified_name + name; return qualified_name + name;
} }
static grpc::string GenerateMessage(const std::vector<std::string> &components, static grpc::string GenerateMessage(const std::vector<std::string>& components,
const grpc::string &name) { const grpc::string& name) {
return "Message<" + WrapInNameSpace(components, name) + ">"; return "Message<" + WrapInNameSpace(components, name) + ">";
} }
// MARK: - Client // MARK: - Client
static void GenerateClientFuncName(const grpc_generator::Method *method, static void GenerateClientFuncName(
grpc_generator::Printer *printer, const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print(vars, printer->Print(vars,
@@ -83,9 +84,9 @@ static void GenerateClientFuncName(const grpc_generator::Method *method,
" ) -> BidirectionalStreamingCall<$Input$, $Output$>"); " ) -> BidirectionalStreamingCall<$Input$, $Output$>");
} }
static void GenerateClientFuncBody(const grpc_generator::Method *method, static void GenerateClientFuncBody(
grpc_generator::Printer *printer, const grpc_generator::Method* method, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
vars["Interceptor"] = vars["Interceptor"] =
"interceptors: self.interceptors?.make$MethodName$Interceptors() ?? []"; "interceptors: self.interceptors?.make$MethodName$Interceptors() ?? []";
@@ -133,9 +134,9 @@ static void GenerateClientFuncBody(const grpc_generator::Method *method,
" )\n"); " )\n");
} }
void GenerateClientProtocol(const grpc_generator::Service *service, void GenerateClientProtocol(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print( printer->Print(
vars, vars,
@@ -207,8 +208,8 @@ void GenerateClientProtocol(const grpc_generator::Service *service,
printer->Print("}\n\n"); printer->Print("}\n\n");
} }
void GenerateClientClass(grpc_generator::Printer *printer, void GenerateClientClass(grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, printer->Print(vars,
"$ACCESS$ final class $ServiceQualifiedName$ServiceClient: " "$ACCESS$ final class $ServiceQualifiedName$ServiceClient: "
@@ -237,7 +238,7 @@ void GenerateClientClass(grpc_generator::Printer *printer,
// MARK: - Server // MARK: - Server
grpc::string GenerateServerFuncName(const grpc_generator::Method *method) { grpc::string GenerateServerFuncName(const grpc_generator::Method* method) {
if (method->NoStreaming()) { if (method->NoStreaming()) {
return "func $MethodName$(request: $Input$" return "func $MethodName$(request: $Input$"
", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>"; ", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>";
@@ -258,7 +259,7 @@ grpc::string GenerateServerFuncName(const grpc_generator::Method *method) {
"-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>"; "-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>";
} }
grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { grpc::string GenerateServerExtensionBody(const grpc_generator::Method* method) {
grpc::string start = " case \"$MethodName$\":\n "; grpc::string start = " case \"$MethodName$\":\n ";
grpc::string interceptors = grpc::string interceptors =
" interceptors: self.interceptors?.make$MethodName$Interceptors() " " interceptors: self.interceptors?.make$MethodName$Interceptors() "
@@ -302,9 +303,9 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) {
return ""; return "";
} }
void GenerateServerProtocol(const grpc_generator::Service *service, void GenerateServerProtocol(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, printer->Print(vars,
"$ACCESS$ protocol $ServiceQualifiedName$Provider: " "$ACCESS$ protocol $ServiceQualifiedName$Provider: "
@@ -375,12 +376,14 @@ void GenerateServerProtocol(const grpc_generator::Service *service,
} }
} // namespace } // namespace
grpc::string Generate(grpc_generator::File *file, grpc::string Generate(grpc_generator::File* file,
const grpc_generator::Service *service) { const grpc_generator::Service* service) {
grpc::string output; grpc::string output;
std::map<grpc::string, grpc::string> vars; std::map<grpc::string, grpc::string> vars;
vars["PATH"] = file->package(); vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); } if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceQualifiedName"] = vars["ServiceQualifiedName"] =
WrapInNameSpace(service->namespace_parts(), service->name()); WrapInNameSpace(service->namespace_parts(), service->name());
vars["ServiceName"] = service->name(); vars["ServiceName"] = service->name();
@@ -394,6 +397,8 @@ grpc::string Generate(grpc_generator::File *file,
GenerateClientClass(&*printer, &vars); GenerateClientClass(&*printer, &vars);
printer->Print("\n"); printer->Print("\n");
GenerateServerProtocol(service, &*printer, &vars); GenerateServerProtocol(service, &*printer, &vars);
printer->Print("\n");
printer->Print("#endif\n");
return output; return output;
} }
@@ -409,6 +414,7 @@ grpc::string GenerateHeader() {
code += "// swiftlint:disable all\n"; code += "// swiftlint:disable all\n";
code += "// swiftformat:disable all\n"; code += "// swiftformat:disable all\n";
code += "\n"; code += "\n";
code += "#if !os(Windows)\n";
code += "import Foundation\n"; code += "import Foundation\n";
code += "import GRPC\n"; code += "import GRPC\n";
code += "import NIO\n"; code += "import NIO\n";
@@ -428,10 +434,7 @@ grpc::string GenerateHeader() {
code += " }\n"; code += " }\n";
code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n"; code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
code += code += " withUnsafeReadableBytes { buffer.writeBytes($0) }\n";
" let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
"Int(self.size))\n";
code += " buffer.writeBytes(buf)\n";
code += " }\n"; code += " }\n";
code += "}\n"; code += "}\n";
code += "extension Message: GRPCFlatBufPayload {}\n"; code += "extension Message: GRPCFlatBufPayload {}\n";

View File

@@ -20,8 +20,8 @@
#include "src/compiler/schema_interface.h" #include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING #ifndef GRPC_CUSTOM_STRING
# include <string> #include <string>
# define GRPC_CUSTOM_STRING std::string #define GRPC_CUSTOM_STRING std::string
#endif #endif
namespace grpc { namespace grpc {
@@ -31,7 +31,7 @@ typedef GRPC_CUSTOM_STRING string;
} // namespace grpc } // namespace grpc
namespace grpc_swift_generator { namespace grpc_swift_generator {
grpc::string Generate(grpc_generator::File *file, grpc::string Generate(grpc_generator::File* file,
const grpc_generator::Service *service); const grpc_generator::Service* service);
grpc::string GenerateHeader(); grpc::string GenerateHeader();
} // namespace grpc_swift_generator } // namespace grpc_swift_generator

View File

@@ -56,9 +56,9 @@ static grpc::string GenerateNamespace(const std::vector<std::string> ns,
// MARK: - Shared code // MARK: - Shared code
static void GenerateImports(const grpc_generator::Service *service, static void GenerateImports(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary, std::map<grpc::string, grpc::string>* dictonary,
const bool grpc_var_import) { const bool grpc_var_import) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print( printer->Print(
@@ -105,9 +105,9 @@ static void GenerateImports(const grpc_generator::Service *service,
// MARK: - Generate Main GRPC Code // MARK: - Generate Main GRPC Code
static void GetStreamType(grpc_generator::Printer *printer, static void GetStreamType(grpc_generator::Printer* printer,
const grpc_generator::Method *method, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
auto client_streaming = method->ClientStreaming() || method->BidiStreaming(); auto client_streaming = method->ClientStreaming() || method->BidiStreaming();
auto server_streaming = method->ServerStreaming() || method->BidiStreaming(); auto server_streaming = method->ServerStreaming() || method->BidiStreaming();
@@ -117,8 +117,9 @@ static void GetStreamType(grpc_generator::Printer *printer,
printer->Print(vars, "responseStream: $ServerStreaming$,\n"); printer->Print(vars, "responseStream: $ServerStreaming$,\n");
} }
static void GenerateSerializeMethod(grpc_generator::Printer *printer, static void GenerateSerializeMethod(
std::map<grpc::string, grpc::string> *dictonary) { grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, "function serialize_$Type$(buffer_args) {\n"); printer->Print(vars, "function serialize_$Type$(buffer_args) {\n");
printer->Indent(); printer->Indent();
@@ -134,8 +135,8 @@ static void GenerateSerializeMethod(grpc_generator::Printer *printer,
} }
static void GenerateDeserializeMethod( static void GenerateDeserializeMethod(
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, "function deserialize_$Type$(buffer) {\n"); printer->Print(vars, "function deserialize_$Type$(buffer) {\n");
printer->Indent(); printer->Indent();
@@ -146,9 +147,9 @@ static void GenerateDeserializeMethod(
printer->Print("}\n\n"); printer->Print("}\n\n");
} }
static void GenerateMethods(const grpc_generator::Service *service, static void GenerateMethods(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
std::set<grpc::string> generated_functions; std::set<grpc::string> generated_functions;
@@ -178,9 +179,9 @@ static void GenerateMethods(const grpc_generator::Service *service,
} }
} }
static void GenerateService(const grpc_generator::Service *service, static void GenerateService(const grpc_generator::Service* service,
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
vars["NAME"] = service->name() + "Service"; vars["NAME"] = service->name() + "Service";
@@ -215,15 +216,17 @@ static void GenerateService(const grpc_generator::Service *service,
} // namespace } // namespace
grpc::string Generate(grpc_generator::File *file, grpc::string Generate(grpc_generator::File* file,
const grpc_generator::Service *service, const grpc_generator::Service* service,
const grpc::string &filename) { const grpc::string& filename) {
grpc::string output; grpc::string output;
std::map<grpc::string, grpc::string> vars; std::map<grpc::string, grpc::string> vars;
vars["PATH"] = file->package(); vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); } if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceName"] = service->name(); vars["ServiceName"] = service->name();
vars["FBSFile"] = service->name() + "_fbs"; vars["FBSFile"] = service->name() + "_fbs";
@@ -240,8 +243,8 @@ namespace {
// MARK: - Generate Interface // MARK: - Generate Interface
static void FillInterface(grpc_generator::Printer *printer, static void FillInterface(grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, printer->Print(vars,
"interface I$ServiceName$Service_I$MethodName$ extends " "interface I$ServiceName$Service_I$MethodName$ extends "
@@ -258,9 +261,9 @@ static void FillInterface(grpc_generator::Printer *printer,
printer->Print("}\n"); printer->Print("}\n");
} }
static void GenerateInterfaces(const grpc_generator::Service *service, static void GenerateInterfaces(
grpc_generator::Printer *printer, const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
for (auto it = 0; it < service->method_count(); it++) { for (auto it = 0; it < service->method_count(); it++) {
auto method = service->method(it); auto method = service->method(it);
@@ -281,8 +284,8 @@ static void GenerateInterfaces(const grpc_generator::Service *service,
} }
static void GenerateExportedInterface( static void GenerateExportedInterface(
const grpc_generator::Service *service, grpc_generator::Printer *printer, const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, printer->Print(vars,
"export interface I$ServiceName$Server extends " "export interface I$ServiceName$Server extends "
@@ -324,9 +327,9 @@ static void GenerateExportedInterface(
printer->Print("}\n"); printer->Print("}\n");
} }
static void GenerateMainInterface(const grpc_generator::Service *service, static void GenerateMainInterface(
grpc_generator::Printer *printer, const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print( printer->Print(
vars, vars,
@@ -351,11 +354,13 @@ static void GenerateMainInterface(const grpc_generator::Service *service,
static grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; } 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( static void GenerateUnaryClientInterface(
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, ";
grpc::string callback = grpc::string callback =
@@ -369,8 +374,8 @@ static void GenerateUnaryClientInterface(
} }
static void GenerateClientWriteStreamInterface( static void GenerateClientWriteStreamInterface(
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
grpc::string main = "$ISPUBLIC$$MethodName$("; grpc::string main = "$ISPUBLIC$$MethodName$(";
grpc::string callback = grpc::string callback =
@@ -386,8 +391,8 @@ static void GenerateClientWriteStreamInterface(
} }
static void GenerateClientReadableStreamInterface( static void GenerateClientReadableStreamInterface(
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, ";
grpc::string end_function = "): grpc.ClientReadableStream<$OUTPUT$>;\n"; grpc::string end_function = "): grpc.ClientReadableStream<$OUTPUT$>;\n";
@@ -398,8 +403,8 @@ static void GenerateClientReadableStreamInterface(
} }
static void GenerateDepluxStreamInterface( static void GenerateDepluxStreamInterface(
grpc_generator::Printer *printer, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
grpc::string main = "$ISPUBLIC$$MethodName$("; grpc::string main = "$ISPUBLIC$$MethodName$(";
grpc::string end_function = grpc::string end_function =
@@ -413,9 +418,9 @@ static void GenerateDepluxStreamInterface(
.c_str()); .c_str());
} }
static void GenerateClientInterface(const grpc_generator::Service *service, static void GenerateClientInterface(
grpc_generator::Printer *printer, const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, "export interface I$ServiceName$Client {\n"); printer->Print(vars, "export interface I$ServiceName$Client {\n");
printer->Indent(); printer->Indent();
@@ -452,8 +457,8 @@ static void GenerateClientInterface(const grpc_generator::Service *service,
} }
static void GenerateClientClassInterface( static void GenerateClientClassInterface(
const grpc_generator::Service *service, grpc_generator::Printer *printer, const grpc_generator::Service* service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> *dictonary) { std::map<grpc::string, grpc::string>* dictonary) {
auto vars = *dictonary; auto vars = *dictonary;
printer->Print(vars, printer->Print(vars,
"export class $ServiceName$Client extends grpc.Client " "export class $ServiceName$Client extends grpc.Client "
@@ -494,10 +499,9 @@ static void GenerateClientClassInterface(
} }
} // namespace } // namespace
grpc::string GenerateInterface(grpc_generator::File* file,
grpc::string GenerateInterface(grpc_generator::File *file, const grpc_generator::Service* service,
const grpc_generator::Service *service, const grpc::string& filename) {
const grpc::string &filename) {
grpc::string output; grpc::string output;
std::set<grpc::string> generated_functions; std::set<grpc::string> generated_functions;
@@ -505,7 +509,9 @@ grpc::string GenerateInterface(grpc_generator::File *file,
vars["PATH"] = file->package(); vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); } if (!file->package().empty()) {
vars["PATH"].append(".");
}
vars["ServiceName"] = service->name(); vars["ServiceName"] = service->name();
vars["FBSFile"] = service->name() + "_fbs"; vars["FBSFile"] = service->name() + "_fbs";

View File

@@ -5,8 +5,8 @@
#include "src/compiler/schema_interface.h" #include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING #ifndef GRPC_CUSTOM_STRING
# include <string> #include <string>
# define GRPC_CUSTOM_STRING std::string #define GRPC_CUSTOM_STRING std::string
#endif #endif
namespace grpc { namespace grpc {
@@ -16,11 +16,11 @@ typedef GRPC_CUSTOM_STRING string;
} // namespace grpc } // namespace grpc
namespace grpc_ts_generator { namespace grpc_ts_generator {
grpc::string Generate(grpc_generator::File *file, grpc::string Generate(grpc_generator::File* file,
const grpc_generator::Service *service, const grpc_generator::Service* service,
const grpc::string &filename); const grpc::string& filename);
grpc::string GenerateInterface(grpc_generator::File *file, grpc::string GenerateInterface(grpc_generator::File* file,
const grpc_generator::Service *service, const grpc_generator::Service* service,
const grpc::string &filename); const grpc::string& filename);
} // namespace grpc_ts_generator } // namespace grpc_ts_generator

View File

@@ -17,3 +17,27 @@ cc_test(
"@com_github_grpc_grpc//:grpc++", "@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.Monster;
import MyGame.Example.Stat; import MyGame.Example.Stat;
import com.google.flatbuffers.FlatBufferBuilder; import com.google.flatbuffers.FlatBufferBuilder;
import java.nio.ByteBuffer;
class GameFactory { 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(); FlatBufferBuilder builder = new FlatBufferBuilder();
int name_offset = builder.createString(monsterName); int name_offset = builder.createString(monsterName);
@@ -38,5 +39,4 @@ class GameFactory {
Stat stat = Stat.getRootAsStat(builder.dataBuffer()); Stat stat = Stat.getRootAsStat(builder.dataBuffer());
return stat; return stat;
} }
} }

View File

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

View File

@@ -33,9 +33,9 @@ void message_builder_tests();
// code. It implements all rpcs specified in the FlatBuffers schema. // code. It implements all rpcs specified in the FlatBuffers schema.
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
virtual ::grpc::Status Store( virtual ::grpc::Status Store(
::grpc::ServerContext *context, ::grpc::ServerContext* context,
const flatbuffers::grpc::Message<Monster> *request, const flatbuffers::grpc::Message<Monster>* request,
flatbuffers::grpc::Message<Stat> *response) override { flatbuffers::grpc::Message<Stat>* response) override {
// Create a response from the incoming request name. // Create a response from the incoming request name.
fbb_.Clear(); fbb_.Clear();
auto stat_offset = CreateStat( auto stat_offset = CreateStat(
@@ -46,9 +46,9 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
return grpc::Status::OK; return grpc::Status::OK;
} }
virtual ::grpc::Status Retrieve( virtual ::grpc::Status Retrieve(
::grpc::ServerContext *context, ::grpc::ServerContext* context,
const flatbuffers::grpc::Message<Stat> *request, const flatbuffers::grpc::Message<Stat>* request,
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer) ::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>>* writer)
override { override {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
fbb_.Clear(); fbb_.Clear();
@@ -73,7 +73,7 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
}; };
// Track the server instance, so we can terminate it later. // Track the server instance, so we can terminate it later.
grpc::Server *server_instance = nullptr; grpc::Server* server_instance = nullptr;
// Mutex to protec this variable. // Mutex to protec this variable.
std::mutex wait_for_server; std::mutex wait_for_server;
std::condition_variable server_instance_cv; std::condition_variable server_instance_cv;
@@ -98,7 +98,8 @@ void RunServer() {
server_instance->Wait(); server_instance->Wait();
} }
template<class Builder> void StoreRPC(MonsterStorage::Stub *stub) { template <class Builder>
void StoreRPC(MonsterStorage::Stub* stub) {
Builder fbb; Builder fbb;
grpc::ClientContext context; grpc::ClientContext context;
// Build a request with the name set. // 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; Builder fbb;
grpc::ClientContext context; grpc::ClientContext context;
fbb.Clear(); fbb.Clear();
@@ -179,7 +181,7 @@ int grpc_server_test() {
return 0; return 0;
} }
int main(int /*argc*/, const char * /*argv*/[]) { int main(int /*argc*/, const char* /*argv*/[]) {
message_builder_tests(); message_builder_tests();
grpc_server_test(); grpc_server_test();

View File

@@ -1,13 +1,13 @@
from __future__ import print_function from __future__ import print_function
from concurrent import futures
import os import os
import sys import sys
import grpc
import flatbuffers 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.Monster as Monster
import MyGame.Example.Stat as Stat import MyGame.Example.Stat as Stat
import MyGame.Example.Vec3 as Vec3 import MyGame.Example.Vec3 as Vec3
@@ -60,7 +60,7 @@ class MonsterStorage(monster_grpc_fb.MonsterStorageServicer):
assert m.InventoryLength() == len(test_inventory) assert m.InventoryLength() == len(test_inventory)
for i in range(0, len(test_inventory)): for i in range(0, len(test_inventory)):
assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1] assert m.Inventory(i) == test_inventory[len(test_inventory) - i - 1]
assert m.TestType() == test_testtype assert m.TestType() == test_testtype
@@ -103,7 +103,7 @@ def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server) monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server)
server.add_insecure_port('[::]:50051') server.add_insecure_port("[::]:50051")
server.start() server.start()
@@ -112,7 +112,7 @@ def serve():
def run(): 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) stub = monster_grpc_fb.MonsterStorageStub(channel)
b = flatbuffers.Builder(0) b = flatbuffers.Builder(0)
@@ -142,7 +142,9 @@ def run():
Monster.MonsterAddHp(b, test_hp) Monster.MonsterAddHp(b, test_hp)
Monster.MonsterAddName(b, name1) Monster.MonsterAddName(b, name1)
Monster.MonsterAddColor(b, test_color) 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.MonsterAddPos(b, pos)
Monster.MonsterAddInventory(b, inv) Monster.MonsterAddInventory(b, inv)
Monster.MonsterAddTestType(b, test_testtype) Monster.MonsterAddTestType(b, test_testtype)
@@ -170,5 +172,5 @@ def run():
count = count + 1 count = count + 1
if __name__ == '__main__': if __name__ == "__main__":
serve() 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

@@ -7,9 +7,9 @@ using MyGame::Example::Any_NONE;
using MyGame::Example::CreateStat; using MyGame::Example::CreateStat;
using MyGame::Example::Vec3; using MyGame::Example::Vec3;
bool verify(flatbuffers::grpc::Message<Monster> &msg, bool verify(flatbuffers::grpc::Message<Monster>& msg,
const std::string &expected_name, Color expected_color) { const std::string& expected_name, Color expected_color) {
const Monster *monster = msg.GetRoot(); const Monster* monster = msg.GetRoot();
const auto name = monster->name()->str(); const auto name = monster->name()->str();
const auto color = monster->color(); const auto color = monster->color();
TEST_EQ(name, expected_name); TEST_EQ(name, expected_name);
@@ -17,8 +17,8 @@ bool verify(flatbuffers::grpc::Message<Monster> &msg,
return (name == expected_name) && (color == expected_color); return (name == expected_name) && (color == expected_color);
} }
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, bool release_n_verify(flatbuffers::grpc::MessageBuilder& mbb,
const std::string &expected_name, Color expected_color) { const std::string& expected_name, Color expected_color) {
flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>(); flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
return verify(msg, expected_name, expected_color); return verify(msg, expected_name, expected_color);
} }
@@ -41,11 +41,13 @@ void builder_move_assign_after_releaseraw_test(
TEST_EQ(src.GetSize(), 0); TEST_EQ(src.GetSize(), 0);
} }
template<class SrcBuilder> template <class SrcBuilder>
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> { struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
static void builder_reusable_after_release_message_test( static void builder_reusable_after_release_message_test(
TestSelector selector) { TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; } if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
return;
}
flatbuffers::grpc::MessageBuilder mb; flatbuffers::grpc::MessageBuilder mb;
std::vector<flatbuffers::grpc::Message<Monster>> buffers; 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) { 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 // FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
// SliceAllocator::allocate in the second iteration. // 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) { 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; flatbuffers::grpc::MessageBuilder mb;
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
@@ -82,14 +88,16 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
mb.Finish(root_offset1); mb.Finish(root_offset1);
size_t size, offset; size_t size, offset;
::grpc::Slice slice; ::grpc::Slice slice;
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice); const uint8_t* buf = mb.ReleaseRaw(size, offset, slice);
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color())); TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
} }
} }
static void builder_reusable_after_release_and_move_assign_test( static void builder_reusable_after_release_and_move_assign_test(
TestSelector selector) { 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 == // FIXME: Release-move_assign loop fails assert(p ==
// GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the // 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( static void builder_reusable_after_releaseraw_and_move_assign_test(
TestSelector selector) { 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; flatbuffers::grpc::MessageBuilder dst;
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
@@ -145,7 +155,7 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
dst.Finish(root_offset1); dst.Finish(root_offset1);
size_t size, offset; size_t size, offset;
::grpc::Slice slice; ::grpc::Slice slice;
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice); const uint8_t* buf = dst.ReleaseRaw(size, offset, slice);
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color())); TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
SrcBuilder src; SrcBuilder src;
@@ -170,7 +180,7 @@ void slice_allocator_tests() {
{ {
size_t size = 2048; size_t size = 2048;
flatbuffers::grpc::SliceAllocator sa1; flatbuffers::grpc::SliceAllocator sa1;
uint8_t *buf = sa1.allocate(size); uint8_t* buf = sa1.allocate(size);
TEST_ASSERT_FUNC(buf != 0); TEST_ASSERT_FUNC(buf != 0);
buf[0] = 100; buf[0] = 100;
buf[size - 1] = 200; buf[size - 1] = 200;
@@ -184,7 +194,7 @@ void slice_allocator_tests() {
// move-assign test // move-assign test
{ {
flatbuffers::grpc::SliceAllocator sa1, sa2; flatbuffers::grpc::SliceAllocator sa1, sa2;
uint8_t *buf = sa1.allocate(2048); uint8_t* buf = sa1.allocate(2048);
sa1 = std::move(sa2); sa1 = std::move(sa2);
// sa1 deletes previously allocated memory in move-assign. // sa1 deletes previously allocated memory in move-assign.
// So buf is no longer usable here. // So buf is no longer usable here.
@@ -194,7 +204,7 @@ void slice_allocator_tests() {
/// This function does not populate exactly the first half of the table. But it /// This function does not populate exactly the first half of the table. But it
/// could. /// could.
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, void populate_first_half(MyGame::Example::MonsterBuilder& wrapper,
flatbuffers::Offset<flatbuffers::String> name_offset) { flatbuffers::Offset<flatbuffers::String> name_offset) {
wrapper.add_name(name_offset); wrapper.add_name(name_offset);
wrapper.add_color(m1_color()); wrapper.add_color(m1_color());
@@ -202,7 +212,7 @@ void populate_first_half(MyGame::Example::MonsterBuilder &wrapper,
/// This function does not populate exactly the second half of the table. But it /// This function does not populate exactly the second half of the table. But it
/// could. /// could.
void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) { void populate_second_half(MyGame::Example::MonsterBuilder& wrapper) {
wrapper.add_hp(77); wrapper.add_hp(77);
wrapper.add_mana(88); wrapper.add_mana(88);
Vec3 vec3; Vec3 vec3;
@@ -216,9 +226,9 @@ void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
/// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack /// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack
/// would be unnecessary. That involves a code-generator change though. /// would be unnecessary. That involves a code-generator change though.
void test_only_hack_update_fbb_reference( void test_only_hack_update_fbb_reference(
MyGame::Example::MonsterBuilder &monsterBuilder, MyGame::Example::MonsterBuilder& monsterBuilder,
flatbuffers::grpc::MessageBuilder &mb) { flatbuffers::grpc::MessageBuilder& mb) {
*reinterpret_cast<flatbuffers::FlatBufferBuilder **>(&monsterBuilder) = &mb; *reinterpret_cast<flatbuffers::FlatBufferBuilder**>(&monsterBuilder) = &mb;
} }
/// This test validates correctness of move conversion of FlatBufferBuilder to a /// This test validates correctness of move conversion of FlatBufferBuilder to a
@@ -358,8 +368,7 @@ void message_builder_tests() {
REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE, REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN, 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( BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
TestSelector(tests, tests + 6)); TestSelector(tests, tests + 6));

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