mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0cede9c90 | ||
|
|
fcc2bee0b6 | ||
|
|
e08da4dea2 | ||
|
|
18538c401c | ||
|
|
e57f4ab2d2 | ||
|
|
deed68db5d | ||
|
|
061d61f3f8 | ||
|
|
cffe0c4546 | ||
|
|
fadd40e402 | ||
|
|
e47dc0e465 | ||
|
|
5c54754790 | ||
|
|
4f7f6dc301 | ||
|
|
0fadaf391d | ||
|
|
4d0e9a8706 | ||
|
|
c05f6783a6 | ||
|
|
a14f4052cf | ||
|
|
9e4ca857b6 | ||
|
|
a2b99084b4 | ||
|
|
85b4effac6 | ||
|
|
790f411542 | ||
|
|
e89de4411d | ||
|
|
256ab3798d | ||
|
|
a59288a019 | ||
|
|
587bbd49a7 | ||
|
|
a9c341545f | ||
|
|
8aa18b6291 | ||
|
|
d727579b6d | ||
|
|
97a30171cb | ||
|
|
0989fc5e59 | ||
|
|
927175ea20 | ||
|
|
6748c373be | ||
|
|
3fab0c6ee4 | ||
|
|
6c8c291559 | ||
|
|
fd4ff23da0 | ||
|
|
f8b69e3308 | ||
|
|
c0394bb09c | ||
|
|
8433eb108c | ||
|
|
f2f9380c86 | ||
|
|
e672dabfea | ||
|
|
9a4ca2764c | ||
|
|
4c7a9c10d3 | ||
|
|
38295a1873 | ||
|
|
31bb0b9726 | ||
|
|
45e5642e91 | ||
|
|
a592f4c89e | ||
|
|
b9d43a557c | ||
|
|
2ece9e25b4 | ||
|
|
2dd2126379 | ||
|
|
f63c130c28 | ||
|
|
e2b26ee19b | ||
|
|
9d686bf433 | ||
|
|
1d26daff3e | ||
|
|
e72e18d9fd | ||
|
|
354d97f6da | ||
|
|
6f7a57eaa0 | ||
|
|
90baa1444b | ||
|
|
0a3b017f09 | ||
|
|
47d35f1053 | ||
|
|
8fb8c2ce1d | ||
|
|
1d063d87cf | ||
|
|
338331b55b | ||
|
|
156a30c753 | ||
|
|
550d2f9048 | ||
|
|
c3a38242e6 | ||
|
|
74c3d7eba2 | ||
|
|
db6eae5c42 | ||
|
|
0e9d79c355 | ||
|
|
b20c4d3aad | ||
|
|
ae145293cc | ||
|
|
e3c76a5cde | ||
|
|
4b9123baff | ||
|
|
f89e0b1a6c | ||
|
|
273f6084e5 | ||
|
|
4a0879458d | ||
|
|
d6f51ea16d | ||
|
|
067dce6e79 | ||
|
|
2ca5f0e72b | ||
|
|
f20d2253ae | ||
|
|
390d438e2a | ||
|
|
6fb2c90d9e | ||
|
|
a7b527d942 | ||
|
|
5d77820b34 | ||
|
|
909ce970ae | ||
|
|
35e2cac6eb | ||
|
|
c39fc9dd9c | ||
|
|
775c6567d1 | ||
|
|
97d9527f6c | ||
|
|
e012054667 | ||
|
|
5235133f32 | ||
|
|
c871df7702 | ||
|
|
a6eeeb3b9c | ||
|
|
3dd02144d5 | ||
|
|
e77926f0ed | ||
|
|
ac23482022 | ||
|
|
8be8a0a713 | ||
|
|
12e341e4f8 | ||
|
|
c36672d803 | ||
|
|
2bfc8e9f01 | ||
|
|
674a9f2aae | ||
|
|
016e6aa13f | ||
|
|
65700441d3 | ||
|
|
dd5bb55cad | ||
|
|
e8423da1b7 | ||
|
|
0980e39c9b | ||
|
|
e73fab27d4 | ||
|
|
92ae532e43 | ||
|
|
7482b25f8b | ||
|
|
3f77dc9a0e | ||
|
|
838c93b843 | ||
|
|
089f48a4a6 | ||
|
|
bf3470c161 | ||
|
|
8f8196e136 | ||
|
|
8ab35b2a5f | ||
|
|
c0ba2870c9 | ||
|
|
22498cf3a9 | ||
|
|
bd37e67ac0 | ||
|
|
a6ee335574 | ||
|
|
71d43f3be9 | ||
|
|
c8db1ca5d4 | ||
|
|
962751a6ec | ||
|
|
06fd6d640c | ||
|
|
acce4ac3f0 | ||
|
|
8fd7861b75 | ||
|
|
c58ae94225 | ||
|
|
2cf7bb7966 | ||
|
|
4e3a66c141 | ||
|
|
d959e23208 | ||
|
|
a9fb540884 | ||
|
|
337eb8b8f7 | ||
|
|
6415ef05d3 | ||
|
|
f069396d1b | ||
|
|
021177af0d | ||
|
|
e1e9f93739 | ||
|
|
15110094eb | ||
|
|
093badb0a0 | ||
|
|
752c7b576d | ||
|
|
7c3e267e1e | ||
|
|
baaffbaedd | ||
|
|
4cb3f222b1 | ||
|
|
eabdbda755 | ||
|
|
bec23700fc | ||
|
|
12f2eedadc | ||
|
|
221eeb2312 | ||
|
|
813d3632ec | ||
|
|
d84bccb0c7 | ||
|
|
b4e67f9bf0 | ||
|
|
54c11932fa | ||
|
|
fbcb3c4236 | ||
|
|
8937dcfd78 | ||
|
|
512d5a6897 | ||
|
|
a92cb5dd7b | ||
|
|
d151dcbb9d | ||
|
|
f1884c66f4 | ||
|
|
72730ecd8a | ||
|
|
fe2bc2b0a7 | ||
|
|
4867c94564 | ||
|
|
ef0eb3701d | ||
|
|
f83ee1af59 | ||
|
|
a5175c513a | ||
|
|
04b10f5a3a | ||
|
|
c121c03456 | ||
|
|
8fd10606c1 | ||
|
|
a1730fcea8 |
@@ -1,41 +0,0 @@
|
||||
:: Copyright 2018 Google Inc. All rights reserved.
|
||||
::
|
||||
:: Licensed under the Apache License, Version 2.0 (the "License");
|
||||
:: you may not use this file except in compliance with the License.
|
||||
:: You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing, software
|
||||
:: distributed under the License is distributed on an "AS IS" BASIS,
|
||||
:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
:: See the License for the specific language governing permissions and
|
||||
:: limitations under the License.
|
||||
set buildtype=Release
|
||||
if "%1"=="-b" set buildtype=%2
|
||||
|
||||
cd tests
|
||||
call generate_code.bat -b %buildtype% || goto FAIL
|
||||
|
||||
:: TODO: Release and Debug builds produce differences here for some reason.
|
||||
git checkout HEAD -- monster_test.bfbs
|
||||
git checkout HEAD -- arrays_test.bfbs
|
||||
|
||||
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||
goto SUCCESS
|
||||
|
||||
:DIFFFOUND
|
||||
@echo "" >&2
|
||||
@echo "ERROR: ********************************************************" >&2
|
||||
@echo "ERROR: The following differences were found after running the" >&2
|
||||
@echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
|
||||
@echo "ERROR: it after making changes in a generator or schema?" >&2
|
||||
@echo "ERROR: ********************************************************" >&2
|
||||
@echo "" >&2
|
||||
@git -c core.autocrlf=true --no-pager diff --binary
|
||||
|
||||
:FAIL
|
||||
set EXITCODE=1
|
||||
:SUCCESS
|
||||
cd ..
|
||||
EXIT /B %EXITCODE%
|
||||
@@ -1,18 +1,18 @@
|
||||
---
|
||||
buildifier: latest
|
||||
platforms:
|
||||
ubuntu1604:
|
||||
build_targets:
|
||||
- "..."
|
||||
test_targets:
|
||||
- "..."
|
||||
ubuntu1804:
|
||||
build_targets:
|
||||
- "..."
|
||||
- "//..."
|
||||
test_targets:
|
||||
- "..."
|
||||
- "//..."
|
||||
ubuntu2004:
|
||||
build_targets:
|
||||
- "//..."
|
||||
test_targets:
|
||||
- "//..."
|
||||
macos:
|
||||
build_targets:
|
||||
- "..."
|
||||
- "//..."
|
||||
test_targets:
|
||||
- "..."
|
||||
- "//..."
|
||||
|
||||
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,18 +2,17 @@ Thank you for submitting a PR!
|
||||
|
||||
Please delete this standard text once you've created your own description.
|
||||
|
||||
Make sure you include the names of the affected language(s) in your PR title.
|
||||
This helps us get the correct maintainers to look at your issue.
|
||||
If you make changes to any of the code generators (`src/idl_gen*`) be sure to
|
||||
build your project, as it will generate code based on the changes. If necessary
|
||||
the code generation script can be directly run (`scripts/generate_code.py`),
|
||||
requires Python3. This allows us to better see the effect of the PR.
|
||||
|
||||
If you make changes to any of the code generators, be sure to run
|
||||
`cd tests && bash generate_code.sh` (or equivalent .bat) and include the generated
|
||||
code changes in the PR. This allows us to better see the effect of the PR.
|
||||
|
||||
If your PR includes C++ code, please adhere to the Google C++ Style Guide,
|
||||
If your PR includes C++ code, please adhere to the
|
||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html),
|
||||
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
|
||||
so only some C++11 support is available.
|
||||
|
||||
For any C++ changes, please make sure to run `sh src/clang-format-git.sh`
|
||||
For any C++ changes, please make sure to run `sh scripts/clang-format-git.sh`
|
||||
|
||||
Include other details as appropriate.
|
||||
|
||||
|
||||
1
.github/labeler.yml
vendored
1
.github/labeler.yml
vendored
@@ -49,6 +49,7 @@ lua:
|
||||
- '**/*.lua'
|
||||
- lua/**/*
|
||||
- src/idl_gen_lua.cpp
|
||||
- src/bfbs_gen_lua.cpp
|
||||
|
||||
lobster:
|
||||
- '**/*.lobster'
|
||||
|
||||
153
.github/workflows/build.yml
vendored
153
.github/workflows/build.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cxx: [g++-9, clang++-9]
|
||||
cxx: [g++-10, clang++-12]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: cmake
|
||||
@@ -23,6 +23,10 @@ jobs:
|
||||
run: make -j4
|
||||
- name: test
|
||||
run: ./flattests
|
||||
- name: make flatc executable
|
||||
run: |
|
||||
chmod +x flatc
|
||||
./flatc --version
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
@@ -30,12 +34,12 @@ jobs:
|
||||
path: flatc
|
||||
|
||||
build-windows:
|
||||
name: Build Windows
|
||||
name: Build Windows 2019
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON .
|
||||
- name: build
|
||||
@@ -50,15 +54,29 @@ jobs:
|
||||
|
||||
build-windows-2017:
|
||||
name: Build Windows 2017
|
||||
runs-on: windows-2016
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
run: cmake -G "Visual Studio 15 2017" -A x64 -DCMAKE_BUILD_TYPE=Release .
|
||||
- name: build
|
||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
||||
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release .
|
||||
- name: build tool version 15 (VS 2017)
|
||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 /p:VisualStudioVersion=15.0
|
||||
- name: test
|
||||
run: Release\flattests.exe
|
||||
|
||||
build-windows-2015:
|
||||
name: Build Windows 2015
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
run: cmake -G "Visual Studio 14 2015" -A x64 -DCMAKE_BUILD_TYPE=Release .
|
||||
- name: build tool version 14 (VS 2015)
|
||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 /p:VisualStudioVersion=14.0
|
||||
- name: test
|
||||
run: Release\flattests.exe
|
||||
|
||||
@@ -72,8 +90,17 @@ jobs:
|
||||
- name: build
|
||||
# NOTE: we need this _build dir to not have xcodebuild's default ./build dir clash with the BUILD file.
|
||||
run: xcodebuild -toolchain clang -configuration Release -target flattests SYMROOT=$(PWD)/_build
|
||||
- name: check that the binary is "universal"
|
||||
run: |
|
||||
info=$(file _build/Release/flatc)
|
||||
echo $info
|
||||
echo $info | grep "universal binary with 2 architectures"
|
||||
- name: test
|
||||
run: _build/Release/flattests
|
||||
- name: make flatc executable
|
||||
run: |
|
||||
chmod +x _build/Release/flatc
|
||||
./_build/Release/flatc --version
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
@@ -103,13 +130,33 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cxx: [g++-9, clang++-9]
|
||||
cxx: [g++-10, clang++-12]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: cmake
|
||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release . && make -j4
|
||||
- name: Generate
|
||||
run: bash scripts/check-generate-code.sh && bash scripts/check-grpc-generated-code.sh
|
||||
run: scripts/check_generate_code.py
|
||||
- name: Generate gRPC
|
||||
run: bash scripts/check-grpc-generated-code.sh
|
||||
|
||||
build-benchmarks:
|
||||
name: Build Benchmarks (on Linux)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cxx: [g++-10]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: cmake
|
||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release . && make -j4
|
||||
- name: Run benchmarks
|
||||
run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}}
|
||||
- name: Upload benchmarks results
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Linux flatbenchmark results ${{matrix.cxx}}
|
||||
path: benchmarks/results_${{matrix.cxx}}
|
||||
|
||||
build-java:
|
||||
name: Build Java
|
||||
@@ -119,21 +166,39 @@ jobs:
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: bash JavaTest.sh
|
||||
|
||||
build-kotlin:
|
||||
name: Build Kotlin
|
||||
|
||||
build-kotlin-macos:
|
||||
name: Build Kotlin MacOS
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt-hotspot'
|
||||
java-version: '11'
|
||||
- name: Build
|
||||
working-directory: kotlin
|
||||
run: ./gradlew clean build allTests
|
||||
working-directory: kotlin
|
||||
run: ./gradlew clean iosX64Test macosX64Test jsTest jsBrowserTest
|
||||
|
||||
build-kotlin-linux:
|
||||
name: Build Kotlin Linux
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt-hotspot'
|
||||
java-version: '8'
|
||||
- name: Build
|
||||
working-directory: kotlin
|
||||
run: ./gradlew jvmMainClasses jvmTest
|
||||
- name: Run Benchmark
|
||||
working-directory: kotlin
|
||||
run: ./gradlew benchmark
|
||||
working-directory: kotlin
|
||||
run: ./gradlew jvmBenchmark
|
||||
- name: Generate Benchmark Report
|
||||
working-directory: kotlin
|
||||
working-directory: kotlin
|
||||
run: |
|
||||
./gradlew jmhReport;
|
||||
mv benchmark/build/reports/benchmarks/main/* benchmark_latest
|
||||
@@ -152,18 +217,6 @@ jobs:
|
||||
working-directory: tests
|
||||
run: bash RustTest.sh
|
||||
|
||||
#build-js:
|
||||
# name: Build JS
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v1
|
||||
# - name: flatc
|
||||
# # FIXME: make test script not rely on flatc
|
||||
# run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j4
|
||||
# - name: test
|
||||
# working-directory: tests
|
||||
# run: bash JavaScriptTest.sh
|
||||
|
||||
build-python:
|
||||
name: Build Python
|
||||
runs-on: ubuntu-latest
|
||||
@@ -185,29 +238,6 @@ jobs:
|
||||
working-directory: tests
|
||||
run: bash GoTest.sh
|
||||
|
||||
#build-csharp:
|
||||
# name: Build CSharp
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v1
|
||||
# - name: test
|
||||
# working-directory: tests/FlatBuffers.Test
|
||||
# run: bash NetTest.sh
|
||||
|
||||
#build-php:
|
||||
# name: Build PHP
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v1
|
||||
# - name: flatc
|
||||
# # FIXME: make test script not rely on flatc
|
||||
# run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j4
|
||||
# - name: test
|
||||
# working-directory: tests
|
||||
# run: |
|
||||
# php phpTest.php
|
||||
# sh phpUnionVectorTest.sh
|
||||
|
||||
build-swift:
|
||||
name: Build Swift
|
||||
runs-on: ubuntu-latest
|
||||
@@ -227,3 +257,18 @@ jobs:
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: sh TypeScriptTest.sh
|
||||
|
||||
build-dart:
|
||||
name: Build Dart
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: dart-lang/setup-dart@v1
|
||||
with:
|
||||
sdk: stable
|
||||
- name: flatc
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j4
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: bash DartTest.sh
|
||||
|
||||
5
.github/workflows/stale.yml
vendored
5
.github/workflows/stale.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v4.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This pull request is stale because it has been open 6 months with no activity. Please comment or this will be closed in 14 days.'
|
||||
@@ -18,3 +18,6 @@ jobs:
|
||||
days-before-stale: 182 # 6 months
|
||||
days-before-close: 14
|
||||
operations-per-run: 1500
|
||||
exempt-issue-labels: not-stale
|
||||
exempt-pr-labels: not-stale
|
||||
exempt-all-milestones: true
|
||||
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -46,6 +46,8 @@ project.properties
|
||||
proguard-project.txt
|
||||
linklint_results
|
||||
Makefile
|
||||
flatbenchmark
|
||||
flatbenchmark.exe
|
||||
flatc
|
||||
flatc.exe
|
||||
flathash
|
||||
@@ -101,7 +103,10 @@ android/build/
|
||||
samples/android/.externalNativeBuild/
|
||||
samples/android/.gradle/
|
||||
samples/android/build/
|
||||
js/flatbuffers.mjs
|
||||
js/**/*.js
|
||||
js/**/*.d.ts
|
||||
mjs/**/*.js
|
||||
mjs/**/*.d.ts
|
||||
/bazel-bin
|
||||
/bazel-flatbuffers
|
||||
/bazel-genfiles
|
||||
@@ -129,10 +134,6 @@ package-lock.json
|
||||
/*.ilk
|
||||
/*.pdb
|
||||
.clwb
|
||||
js/**/*.js
|
||||
js/**/*.d.ts
|
||||
mjs/**/*.js
|
||||
mjs/**/*.d.ts
|
||||
yarn-error.log
|
||||
.cache/
|
||||
/flatbuffers.lib
|
||||
@@ -141,3 +142,8 @@ yarn-error.log
|
||||
**/vendor
|
||||
**/go.sum
|
||||
flatbuffers.pc
|
||||
**/FlatBuffers.Test.Swift.xcodeproj
|
||||
**/html/**
|
||||
**/latex/**
|
||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR
|
||||
_deps/
|
||||
@@ -115,7 +115,6 @@ matrix:
|
||||
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||
- cmake --build . --target all --clean-first -- -j${JOBS}
|
||||
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash scripts/check-generate-code.sh
|
||||
|
||||
- language: cpp
|
||||
os: osx
|
||||
@@ -140,7 +139,6 @@ matrix:
|
||||
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||
- cmake --build . -- -j${JOBS}
|
||||
- DYLD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash scripts/check-generate-code.sh
|
||||
|
||||
- <<: *conan-linux-master
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
|
||||
@@ -21,7 +21,7 @@ source ~/.nvm/nvm.sh
|
||||
nvm alias default node
|
||||
nvm use default
|
||||
|
||||
sh src/clang-format-git.sh
|
||||
sh scripts/clang-format-git.sh
|
||||
|
||||
# Check formatting for go lang
|
||||
|
||||
|
||||
30
BUILD.bazel
30
BUILD.bazel
@@ -10,6 +10,20 @@ exports_files([
|
||||
"LICENSE",
|
||||
])
|
||||
|
||||
config_setting(
|
||||
name = "platform_freebsd",
|
||||
constraint_values = [
|
||||
"@platforms//os:freebsd",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "platform_openbsd",
|
||||
constraint_values = [
|
||||
"@platforms//os:openbsd",
|
||||
],
|
||||
)
|
||||
|
||||
# Public flatc library to compile flatbuffer files at runtime.
|
||||
cc_library(
|
||||
name = "flatbuffers",
|
||||
@@ -23,8 +37,16 @@ cc_library(
|
||||
filegroup(
|
||||
name = "public_headers",
|
||||
srcs = [
|
||||
"include/flatbuffers/allocator.h",
|
||||
"include/flatbuffers/array.h",
|
||||
"include/flatbuffers/base.h",
|
||||
"include/flatbuffers/bfbs_generator.h",
|
||||
"include/flatbuffers/buffer.h",
|
||||
"include/flatbuffers/buffer_ref.h",
|
||||
"include/flatbuffers/code_generators.h",
|
||||
"include/flatbuffers/default_allocator.h",
|
||||
"include/flatbuffers/detached_buffer.h",
|
||||
"include/flatbuffers/flatbuffer_builder.h",
|
||||
"include/flatbuffers/flatbuffers.h",
|
||||
"include/flatbuffers/flexbuffers.h",
|
||||
"include/flatbuffers/grpc.h",
|
||||
@@ -35,7 +57,13 @@ filegroup(
|
||||
"include/flatbuffers/reflection_generated.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/string.h",
|
||||
"include/flatbuffers/struct.h",
|
||||
"include/flatbuffers/table.h",
|
||||
"include/flatbuffers/util.h",
|
||||
"include/flatbuffers/vector.h",
|
||||
"include/flatbuffers/vector_downward.h",
|
||||
"include/flatbuffers/verifier.h",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -73,6 +101,8 @@ cc_library(
|
||||
"include/flatbuffers/flexbuffers.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
"include/flatbuffers/vector.h",
|
||||
"include/flatbuffers/verifier.h",
|
||||
],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
set(VERSION_MAJOR 2)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_PATCH 5)
|
||||
set(VERSION_COMMIT 0)
|
||||
|
||||
find_program(GIT git)
|
||||
if(GIT)
|
||||
execute_process(
|
||||
COMMAND ${GIT} describe
|
||||
COMMAND ${GIT} describe --tags
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
|
||||
119
CMakeLists.txt
119
CMakeLists.txt
@@ -1,9 +1,19 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
project(FlatBuffers
|
||||
DESCRIPTION "Flatbuffers serialization library"
|
||||
VERSION 2.0.0
|
||||
LANGUAGES CXX)
|
||||
else()
|
||||
project(FlatBuffers)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
include(CMake/Version.cmake)
|
||||
|
||||
# generate compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
project(FlatBuffers)
|
||||
|
||||
# NOTE: Code coverage only works on Linux & OSX.
|
||||
option(FLATBUFFERS_CODE_COVERAGE "Enable the code coverage build option." OFF)
|
||||
@@ -16,6 +26,9 @@ option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
|
||||
option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag"
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
|
||||
option(FLATBUFFERS_BUILD_BENCHMARKS "Enable the build of flatbenchmark. \"
|
||||
Requires C++11."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
|
||||
option(FLATBUFFERS_BUILD_SHAREDLIB
|
||||
"Enable the build of the flatbuffers shared library"
|
||||
@@ -43,6 +56,9 @@ option(FLATBUFFERS_ENABLE_PCH
|
||||
Only work if CMake supports 'target_precompile_headers'. \"
|
||||
This can speed up compilation time."
|
||||
OFF)
|
||||
option(FLATBUFFERS_SKIP_MONSTER_EXTRA
|
||||
"Skip generating monster_extra.fbs that contains non-supported numerical\"
|
||||
types." OFF)
|
||||
|
||||
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
message(WARNING
|
||||
@@ -58,6 +74,8 @@ endif()
|
||||
|
||||
# Auto-detect locale-narrow 'strtod_l' and 'strtoull_l' functions.
|
||||
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 0)
|
||||
if(MSVC)
|
||||
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
@@ -73,17 +91,31 @@ endif()
|
||||
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/allocator.h
|
||||
include/flatbuffers/array.h
|
||||
include/flatbuffers/base.h
|
||||
include/flatbuffers/bfbs_generator.h
|
||||
include/flatbuffers/buffer.h
|
||||
include/flatbuffers/buffer_ref.h
|
||||
include/flatbuffers/default_allocator.h
|
||||
include/flatbuffers/detached_buffer.h
|
||||
include/flatbuffers/flatbuffer_builder.h
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
include/flatbuffers/idl.h
|
||||
include/flatbuffers/util.h
|
||||
include/flatbuffers/minireflect.h
|
||||
include/flatbuffers/reflection.h
|
||||
include/flatbuffers/reflection_generated.h
|
||||
include/flatbuffers/stl_emulation.h
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/registry.h
|
||||
include/flatbuffers/minireflect.h
|
||||
include/flatbuffers/stl_emulation.h
|
||||
include/flatbuffers/string.h
|
||||
include/flatbuffers/struct.h
|
||||
include/flatbuffers/table.h
|
||||
include/flatbuffers/util.h
|
||||
include/flatbuffers/vector.h
|
||||
include/flatbuffers/vector_downward.h
|
||||
include/flatbuffers/verifier.h
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
src/reflection.cpp
|
||||
@@ -110,7 +142,10 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/idl_gen_swift.cpp
|
||||
src/flatc.cpp
|
||||
src/flatc_main.cpp
|
||||
src/bfbs_gen.h
|
||||
src/bfbs_gen_lua.h
|
||||
include/flatbuffers/code_generators.h
|
||||
src/bfbs_gen_lua.cpp
|
||||
src/code_generators.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
@@ -220,10 +255,6 @@ if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||
# do not apply any global settings if the toolchain
|
||||
# is being configured externally
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -250,8 +281,14 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
"${CMAKE_CXX_FLAGS} -fsigned-char")
|
||||
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
|
||||
list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Werror=unused-private-field") # enable warning
|
||||
@@ -382,8 +419,8 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
# - micro updated every release when there is no API/ABI changes
|
||||
# - minor updated when there are additions in API/ABI
|
||||
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||
set(FlatBuffers_Library_SONAME_MAJOR "2")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.0.0")
|
||||
set(FlatBuffers_Library_SONAME_MAJOR ${VERSION_MAJOR})
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||
@@ -438,11 +475,12 @@ function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
message(STATUS "`${SRC_FBS}`: add generation of binary (.bfbs) schema")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
# For details about flags see generate_code.py
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
-b --schema --bfbs-comments --bfbs-builtins
|
||||
--bfbs-filenames ${SRC_FBS_DIR}
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
@@ -460,7 +498,7 @@ function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ embedded binary schema code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_bfbs_generated.h" GEN_BFBS_HEADER ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
# For details about flags see generate_code.py
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BFBS_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
@@ -468,6 +506,7 @@ function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
${OPT}
|
||||
--bfbs-comments --bfbs-builtins --bfbs-gen-embed
|
||||
--bfbs-filenames ${SRC_FBS_DIR}
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
@@ -476,6 +515,37 @@ function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
register_generated_output(${GEN_BFBS_HEADER})
|
||||
endfunction()
|
||||
|
||||
# Look if we have python 3 installed so that we can run the generate code python
|
||||
# script after flatc is built.
|
||||
find_package(PythonInterp 3)
|
||||
|
||||
if(PYTHONINTERP_FOUND AND
|
||||
# Skip doing this if the MSVC version is below VS 12.
|
||||
# https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html
|
||||
(NOT MSVC OR MSVC_VERSION GREATER 1800))
|
||||
if(WIN32)
|
||||
set(GENERATION_SCRIPT py scripts/generate_code.py)
|
||||
else()
|
||||
set(GENERATION_SCRIPT scripts/generate_code.py)
|
||||
endif()
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
# Need to set --cpp-std c++-0x options
|
||||
set(GENERATION_SCRIPT ${GENERATION_SCRIPT} --cpp-0x)
|
||||
endif()
|
||||
if(FLATBUFFERS_SKIP_MONSTER_EXTRA)
|
||||
set(GENERATION_SCRIPT ${GENERATION_SCRIPT} --skip-monster-extra)
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET flatc
|
||||
POST_BUILD
|
||||
COMMAND ${GENERATION_SCRIPT} --flatc "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Running ${GENERATION_SCRIPT}..."
|
||||
VERBATIM)
|
||||
else()
|
||||
message("No Python3 interpreter found! Unable to generate files automatically.")
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
@@ -483,9 +553,9 @@ if(FLATBUFFERS_BUILD_TESTS)
|
||||
# TODO Add (monster_test.fbs monsterdata_test.json)->monsterdata_test.mon
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test1.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test2.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/union_vector/union_vector.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test1.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test2.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/union_vector/union_vector.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp(tests/optional_scalars.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
|
||||
@@ -517,7 +587,7 @@ if(FLATBUFFERS_BUILD_TESTS)
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
# Don't generate header for flattests_cpp17 target.
|
||||
# This target uses "generated_cpp17/monster_test_generated.h"
|
||||
# produced by direct call of generate_code.bat(sh) script.
|
||||
# produced by direct call of generate_code.py script.
|
||||
add_executable(flattests_cpp17 ${FlatBuffers_Tests_CPP17_SRCS})
|
||||
add_dependencies(flattests_cpp17 generated_code)
|
||||
target_compile_features(flattests_cpp17 PRIVATE cxx_std_17)
|
||||
@@ -545,6 +615,7 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
|
||||
find_package(Threads REQUIRED)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${GRPC_INSTALL_PATH})
|
||||
find_package(absl CONFIG REQUIRED)
|
||||
find_package(protobuf CONFIG REQUIRED)
|
||||
find_package(gRPC CONFIG REQUIRED)
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
@@ -556,7 +627,6 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/Version.cmake)
|
||||
|
||||
if(FLATBUFFERS_INSTALL)
|
||||
include(GNUInstallDirs)
|
||||
@@ -676,3 +746,8 @@ if(UNIX)
|
||||
include(CPack)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Include for running Google Benchmarks.
|
||||
if(FLATBUFFERS_BUILD_BENCHMARKS AND CMAKE_VERSION VERSION_GREATER 3.13)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
@@ -11,7 +11,7 @@ If you are interesting in contributing to the flatbuffers project, please take a
|
||||
|
||||
## C++
|
||||
|
||||
C++ uses `clang-format` as it's formatter. Run the following script `sh src/clang-format-git.sh`, and it should style the C++ code according to [google style guide](https://google.github.io/styleguide/cppguide.html).
|
||||
C++ uses `clang-format` as it's formatter. Run the following script `sh scripts/clang-format-git.sh`, and it should style the C++ code according to [google style guide](https://google.github.io/styleguide/cppguide.html).
|
||||
|
||||
## Swift
|
||||
|
||||
|
||||
11
SECURITY.md
Normal file
11
SECURITY.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a security issue, please use http://g.co/vulnz. We use
|
||||
http://g.co/vulnz for our intake, and do coordination and disclosure here on
|
||||
GitHub (including using GitHub Security Advisory). The Google Security Team will
|
||||
respond within 5 working days of your report on g.co/vulnz.
|
||||
|
||||
Select the `I want to report a technical security or an abuse risk related bug
|
||||
in a Google product (SQLi, XSS, etc.)` option and complete the form.
|
||||
@@ -29,7 +29,7 @@ http_archive(
|
||||
)
|
||||
|
||||
##### GRPC
|
||||
_GRPC_VERSION = "1.36.1"
|
||||
_GRPC_VERSION = "1.39.0"
|
||||
|
||||
http_archive(
|
||||
name = "com_github_grpc_grpc",
|
||||
|
||||
@@ -101,16 +101,6 @@ android {
|
||||
|
||||
flavorDimensions "stl-variant"
|
||||
productFlavors {
|
||||
stlport {
|
||||
dimension "stl-variant"
|
||||
applicationIdSuffix ".stlport"
|
||||
versionNameSuffix "-stlport"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=stlport_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
gnustl {
|
||||
dimension "stl-variant"
|
||||
applicationIdSuffix ".gnustl"
|
||||
|
||||
@@ -15,17 +15,31 @@ set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fsigned-char")
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/allocator.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/array.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/base.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/bfbs_generator.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/buffer.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/buffer_ref.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/default_allocator.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/detached_buffer.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffer_builder.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffers.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/flexbuffers.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/hash.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/idl.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/util.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/minireflect.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/reflection.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/reflection_generated.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/stl_emulation.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/flexbuffers.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/registry.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/minireflect.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/stl_emulation.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/string.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/struct.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/table.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/util.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/vector.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/vector_downward.h
|
||||
${FLATBUFFERS_SRC}/include/flatbuffers/verifier.h
|
||||
${FLATBUFFERS_SRC}/src/idl_parser.cpp
|
||||
${FLATBUFFERS_SRC}/src/idl_gen_text.cpp
|
||||
${FLATBUFFERS_SRC}/src/reflection.cpp
|
||||
|
||||
17
appveyor.yml
17
appveyor.yml
@@ -11,21 +11,11 @@ environment:
|
||||
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
|
||||
CMAKE_OPTIONS: ""
|
||||
CPP_TEST_OPTIONS: ""
|
||||
CHECK_GEN_CODE: 1
|
||||
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "10 2010"
|
||||
CMAKE_OPTIONS: "-DFLATBUFFERS_BUILD_LEGACY=1"
|
||||
CPP_TEST_OPTIONS: "--std-cpp c++0x"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "12 2013"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "14 2015"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
platform:
|
||||
- x86
|
||||
@@ -36,7 +26,6 @@ configuration:
|
||||
- Release
|
||||
|
||||
before_build:
|
||||
- set MONSTER_EXTRA=%MONSTER_EXTRA%
|
||||
- cmake . -G"Visual Studio %CMAKE_VS_VERSION%" -DFLATBUFFERS_CODE_SANITIZE=1 %CMAKE_OPTIONS%
|
||||
# This cuts down on a lot of noise generated by xamarin warnings.
|
||||
- if exist "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
@@ -54,10 +43,8 @@ install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
|
||||
test_script:
|
||||
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
|
||||
- if [%CHECK_GEN_CODE%]==[1] (call py scripts/check_generate_code.py "%CPP_TEST_OPTIONS%")
|
||||
- "cd tests"
|
||||
- rem "Building all code"
|
||||
- generate_code.bat -b %CONFIGURATION% %CPP_TEST_OPTIONS%
|
||||
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "cd .."
|
||||
|
||||
81
benchmarks/CMakeLists.txt
Normal file
81
benchmarks/CMakeLists.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
# Setup for running Google Benchmarks (https://github.com/google/benchmark) on
|
||||
# flatbuffers. This requires both that benchmark library and its depenency gtest
|
||||
# to build. Instead of including them here or doing a submodule, this uses
|
||||
# FetchContent (https://cmake.org/cmake/help/latest/module/FetchContent.html) to
|
||||
# grab the dependencies at config time. This requires CMake 3.14 or higher.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
include(FetchContent)
|
||||
|
||||
# No particular reason for the specific GIT_TAGs for the following repos, they
|
||||
# were just the latest releases when this was added.
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0
|
||||
)
|
||||
FetchContent_Declare(
|
||||
googlebenchmark
|
||||
GIT_REPOSITORY https://github.com/google/benchmark.git
|
||||
GIT_TAG f91b6b42b1b9854772a90ae9501464a161707d1e # v1.6.0
|
||||
)
|
||||
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker
|
||||
# settings.
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(
|
||||
googletest
|
||||
googlebenchmark
|
||||
)
|
||||
|
||||
set(CPP_BENCH_DIR cpp)
|
||||
set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers)
|
||||
set(CPP_RAW_BENCH_DIR ${CPP_BENCH_DIR}/raw)
|
||||
set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs)
|
||||
set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h)
|
||||
|
||||
set(FlatBenchmark_SRCS
|
||||
${CPP_BENCH_DIR}/benchmark_main.cpp
|
||||
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
||||
${CPP_RAW_BENCH_DIR}/raw_bench.cpp
|
||||
${CPP_BENCH_FB_GEN}
|
||||
)
|
||||
|
||||
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
||||
# flatc itself, thus it depends on flatc. This also depends on the C++ runtime
|
||||
# flatbuffers and the schema file itself, so it should auto-generated at the
|
||||
# correct times.
|
||||
add_custom_command(
|
||||
OUTPUT ${CPP_BENCH_FB_GEN}
|
||||
COMMAND
|
||||
"${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp
|
||||
-o ${CPP_FB_BENCH_DIR}
|
||||
${CPP_BENCH_FBS}
|
||||
DEPENDS
|
||||
flatc
|
||||
flatbuffers
|
||||
${CPP_BENCH_FBS}
|
||||
COMMENT "Run Flatbuffers Benchmark Codegen: ${CPP_BENCH_FB_GEN}"
|
||||
VERBATIM)
|
||||
|
||||
# The main flatbuffers benchmark executable
|
||||
add_executable(flatbenchmark ${FlatBenchmark_SRCS})
|
||||
|
||||
# Benchmark requires C++11
|
||||
target_compile_features(flatbenchmark PUBLIC
|
||||
cxx_std_11
|
||||
)
|
||||
|
||||
# Set the output directory to the root binary directory
|
||||
set_target_properties(flatbenchmark
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# The includes of the benchmark files are fully qualified from flatbuffers root.
|
||||
target_include_directories(flatbenchmark PUBLIC ${CMAKE_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(flatbenchmark
|
||||
benchmark::benchmark_main # _main to use their entry point
|
||||
gtest # Link to gtest so we can also assert in the benchmarks
|
||||
)
|
||||
19
benchmarks/cpp/bench.h
Normal file
19
benchmarks/cpp/bench.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef BENCHMARKS_CPP_BENCH_H_
|
||||
#define BENCHMARKS_CPP_BENCH_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct Bench {
|
||||
virtual ~Bench() {}
|
||||
|
||||
inline void Add(int64_t value) { sum += value; }
|
||||
|
||||
virtual uint8_t *Encode(void *buf, int64_t &len) = 0;
|
||||
virtual void *Decode(void *buf, int64_t len) = 0;
|
||||
virtual int64_t Use(void *decoded) = 0;
|
||||
virtual void Dealloc(void *decoded) = 0;
|
||||
|
||||
int64_t sum = 0;
|
||||
};
|
||||
|
||||
#endif // BENCHMARKS_CPP_BENCH_H_
|
||||
96
benchmarks/cpp/benchmark_main.cpp
Normal file
96
benchmarks/cpp/benchmark_main.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "benchmarks/cpp/bench.h"
|
||||
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
||||
#include "benchmarks/cpp/raw/raw_bench.h"
|
||||
|
||||
static inline void Encode(benchmark::State &state,
|
||||
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
||||
int64_t length;
|
||||
for (auto _ : state) {
|
||||
bench->Encode(buffer, length);
|
||||
benchmark::DoNotOptimize(length);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Decode(benchmark::State &state,
|
||||
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
||||
int64_t length;
|
||||
uint8_t *encoded = bench->Encode(buffer, length);
|
||||
|
||||
for (auto _ : state) {
|
||||
void *decoded = bench->Decode(encoded, length);
|
||||
benchmark::DoNotOptimize(decoded);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Use(benchmark::State &state, std::unique_ptr<Bench> &bench,
|
||||
uint8_t *buffer, int64_t check_sum) {
|
||||
int64_t length;
|
||||
uint8_t *encoded = bench->Encode(buffer, length);
|
||||
void *decoded = bench->Decode(encoded, length);
|
||||
|
||||
int64_t sum = 0;
|
||||
|
||||
for (auto _ : state) { sum = bench->Use(decoded); }
|
||||
|
||||
EXPECT_EQ(sum, check_sum);
|
||||
}
|
||||
|
||||
static void BM_Flatbuffers_Encode(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
StaticAllocator allocator(&buffer[0]);
|
||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||
Encode(state, bench, buffer);
|
||||
}
|
||||
BENCHMARK(BM_Flatbuffers_Encode);
|
||||
|
||||
static void BM_Flatbuffers_Decode(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
StaticAllocator allocator(&buffer[0]);
|
||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||
Decode(state, bench, buffer);
|
||||
}
|
||||
BENCHMARK(BM_Flatbuffers_Decode);
|
||||
|
||||
static void BM_Flatbuffers_Use(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
StaticAllocator allocator(&buffer[0]);
|
||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||
Use(state, bench, buffer, 218812692406581874);
|
||||
}
|
||||
BENCHMARK(BM_Flatbuffers_Use);
|
||||
|
||||
static void BM_Raw_Encode(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
std::unique_ptr<Bench> bench = NewRawBench();
|
||||
Encode(state, bench, buffer);
|
||||
}
|
||||
BENCHMARK(BM_Raw_Encode);
|
||||
|
||||
static void BM_Raw_Decode(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
std::unique_ptr<Bench> bench = NewRawBench();
|
||||
Decode(state, bench, buffer);
|
||||
}
|
||||
BENCHMARK(BM_Raw_Decode);
|
||||
|
||||
static void BM_Raw_Use(benchmark::State &state) {
|
||||
const int64_t kBufferLength = 1024;
|
||||
uint8_t buffer[kBufferLength];
|
||||
|
||||
std::unique_ptr<Bench> bench = NewRawBench();
|
||||
Use(state, bench, buffer, 218812692406581874);
|
||||
}
|
||||
BENCHMARK(BM_Raw_Use);
|
||||
52
benchmarks/cpp/flatbuffers/bench.fbs
Normal file
52
benchmarks/cpp/flatbuffers/bench.fbs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2021 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
// trying to represent a typical mix of datatypes:
|
||||
// 1 array of 3 elements, each element: 1 string, 3 nested objects, 9 scalars
|
||||
// root element has the array, additional string and an enum
|
||||
|
||||
namespace benchmarks_flatbuffers;
|
||||
|
||||
enum Enum : short { Apples, Pears, Bananas}
|
||||
|
||||
struct Foo {
|
||||
id:ulong;
|
||||
count:short;
|
||||
prefix:byte;
|
||||
length:uint;
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
parent:Foo;
|
||||
time:int;
|
||||
ratio:float;
|
||||
size:ushort;
|
||||
}
|
||||
|
||||
table FooBar {
|
||||
sibling:Bar;
|
||||
name:string;
|
||||
rating:double;
|
||||
postfix:ubyte;
|
||||
}
|
||||
|
||||
table FooBarContainer {
|
||||
list:[FooBar]; // 3 copies of the above
|
||||
initialized:bool;
|
||||
fruit:Enum;
|
||||
location:string;
|
||||
}
|
||||
|
||||
root_type FooBarContainer;
|
||||
347
benchmarks/cpp/flatbuffers/bench_generated.h
Normal file
347
benchmarks/cpp/flatbuffers/bench_generated.h
Normal file
@@ -0,0 +1,347 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
||||
#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
namespace benchmarks_flatbuffers {
|
||||
|
||||
struct Foo;
|
||||
|
||||
struct Bar;
|
||||
|
||||
struct FooBar;
|
||||
struct FooBarBuilder;
|
||||
|
||||
struct FooBarContainer;
|
||||
struct FooBarContainerBuilder;
|
||||
|
||||
enum Enum : int16_t {
|
||||
Enum_Apples = 0,
|
||||
Enum_Pears = 1,
|
||||
Enum_Bananas = 2,
|
||||
Enum_MIN = Enum_Apples,
|
||||
Enum_MAX = Enum_Bananas
|
||||
};
|
||||
|
||||
inline const Enum (&EnumValuesEnum())[3] {
|
||||
static const Enum values[] = {
|
||||
Enum_Apples,
|
||||
Enum_Pears,
|
||||
Enum_Bananas
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesEnum() {
|
||||
static const char * const names[4] = {
|
||||
"Apples",
|
||||
"Pears",
|
||||
"Bananas",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameEnum(Enum e) {
|
||||
if (flatbuffers::IsOutRange(e, Enum_Apples, Enum_Bananas)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesEnum()[index];
|
||||
}
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
uint64_t id_;
|
||||
int16_t count_;
|
||||
int8_t prefix_;
|
||||
int8_t padding0__;
|
||||
uint32_t length_;
|
||||
|
||||
public:
|
||||
Foo()
|
||||
: id_(0),
|
||||
count_(0),
|
||||
prefix_(0),
|
||||
padding0__(0),
|
||||
length_(0) {
|
||||
(void)padding0__;
|
||||
}
|
||||
Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length)
|
||||
: id_(flatbuffers::EndianScalar(_id)),
|
||||
count_(flatbuffers::EndianScalar(_count)),
|
||||
prefix_(flatbuffers::EndianScalar(_prefix)),
|
||||
padding0__(0),
|
||||
length_(flatbuffers::EndianScalar(_length)) {
|
||||
(void)padding0__;
|
||||
}
|
||||
uint64_t id() const {
|
||||
return flatbuffers::EndianScalar(id_);
|
||||
}
|
||||
int16_t count() const {
|
||||
return flatbuffers::EndianScalar(count_);
|
||||
}
|
||||
int8_t prefix() const {
|
||||
return flatbuffers::EndianScalar(prefix_);
|
||||
}
|
||||
uint32_t length() const {
|
||||
return flatbuffers::EndianScalar(length_);
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(Foo, 16);
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
benchmarks_flatbuffers::Foo parent_;
|
||||
int32_t time_;
|
||||
float ratio_;
|
||||
uint16_t size_;
|
||||
int16_t padding0__; int32_t padding1__;
|
||||
|
||||
public:
|
||||
Bar()
|
||||
: parent_(),
|
||||
time_(0),
|
||||
ratio_(0),
|
||||
size_(0),
|
||||
padding0__(0),
|
||||
padding1__(0) {
|
||||
(void)padding0__;
|
||||
(void)padding1__;
|
||||
}
|
||||
Bar(const benchmarks_flatbuffers::Foo &_parent, int32_t _time, float _ratio, uint16_t _size)
|
||||
: parent_(_parent),
|
||||
time_(flatbuffers::EndianScalar(_time)),
|
||||
ratio_(flatbuffers::EndianScalar(_ratio)),
|
||||
size_(flatbuffers::EndianScalar(_size)),
|
||||
padding0__(0),
|
||||
padding1__(0) {
|
||||
(void)padding0__;
|
||||
(void)padding1__;
|
||||
}
|
||||
const benchmarks_flatbuffers::Foo &parent() const {
|
||||
return parent_;
|
||||
}
|
||||
int32_t time() const {
|
||||
return flatbuffers::EndianScalar(time_);
|
||||
}
|
||||
float ratio() const {
|
||||
return flatbuffers::EndianScalar(ratio_);
|
||||
}
|
||||
uint16_t size() const {
|
||||
return flatbuffers::EndianScalar(size_);
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(Bar, 32);
|
||||
|
||||
struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef FooBarBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_SIBLING = 4,
|
||||
VT_NAME = 6,
|
||||
VT_RATING = 8,
|
||||
VT_POSTFIX = 10
|
||||
};
|
||||
const benchmarks_flatbuffers::Bar *sibling() const {
|
||||
return GetStruct<const benchmarks_flatbuffers::Bar *>(VT_SIBLING);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
double rating() const {
|
||||
return GetField<double>(VT_RATING, 0.0);
|
||||
}
|
||||
uint8_t postfix() const {
|
||||
return GetField<uint8_t>(VT_POSTFIX, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<benchmarks_flatbuffers::Bar>(verifier, VT_SIBLING) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.VerifyString(name()) &&
|
||||
VerifyField<double>(verifier, VT_RATING) &&
|
||||
VerifyField<uint8_t>(verifier, VT_POSTFIX) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FooBarBuilder {
|
||||
typedef FooBar Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_sibling(const benchmarks_flatbuffers::Bar *sibling) {
|
||||
fbb_.AddStruct(FooBar::VT_SIBLING, sibling);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(FooBar::VT_NAME, name);
|
||||
}
|
||||
void add_rating(double rating) {
|
||||
fbb_.AddElement<double>(FooBar::VT_RATING, rating, 0.0);
|
||||
}
|
||||
void add_postfix(uint8_t postfix) {
|
||||
fbb_.AddElement<uint8_t>(FooBar::VT_POSTFIX, postfix, 0);
|
||||
}
|
||||
explicit FooBarBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<FooBar> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FooBar>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FooBar> CreateFooBar(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const benchmarks_flatbuffers::Bar *sibling = nullptr,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
double rating = 0.0,
|
||||
uint8_t postfix = 0) {
|
||||
FooBarBuilder builder_(_fbb);
|
||||
builder_.add_rating(rating);
|
||||
builder_.add_name(name);
|
||||
builder_.add_sibling(sibling);
|
||||
builder_.add_postfix(postfix);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FooBar> CreateFooBarDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const benchmarks_flatbuffers::Bar *sibling = nullptr,
|
||||
const char *name = nullptr,
|
||||
double rating = 0.0,
|
||||
uint8_t postfix = 0) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
return benchmarks_flatbuffers::CreateFooBar(
|
||||
_fbb,
|
||||
sibling,
|
||||
name__,
|
||||
rating,
|
||||
postfix);
|
||||
}
|
||||
|
||||
struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef FooBarContainerBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_LIST = 4,
|
||||
VT_INITIALIZED = 6,
|
||||
VT_FRUIT = 8,
|
||||
VT_LOCATION = 10
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *>(VT_LIST);
|
||||
}
|
||||
bool initialized() const {
|
||||
return GetField<uint8_t>(VT_INITIALIZED, 0) != 0;
|
||||
}
|
||||
benchmarks_flatbuffers::Enum fruit() const {
|
||||
return static_cast<benchmarks_flatbuffers::Enum>(GetField<int16_t>(VT_FRUIT, 0));
|
||||
}
|
||||
const flatbuffers::String *location() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_LOCATION);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_LIST) &&
|
||||
verifier.VerifyVector(list()) &&
|
||||
verifier.VerifyVectorOfTables(list()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_INITIALIZED) &&
|
||||
VerifyField<int16_t>(verifier, VT_FRUIT) &&
|
||||
VerifyOffset(verifier, VT_LOCATION) &&
|
||||
verifier.VerifyString(location()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct FooBarContainerBuilder {
|
||||
typedef FooBarContainer Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_list(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list) {
|
||||
fbb_.AddOffset(FooBarContainer::VT_LIST, list);
|
||||
}
|
||||
void add_initialized(bool initialized) {
|
||||
fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED, static_cast<uint8_t>(initialized), 0);
|
||||
}
|
||||
void add_fruit(benchmarks_flatbuffers::Enum fruit) {
|
||||
fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT, static_cast<int16_t>(fruit), 0);
|
||||
}
|
||||
void add_location(flatbuffers::Offset<flatbuffers::String> location) {
|
||||
fbb_.AddOffset(FooBarContainer::VT_LOCATION, location);
|
||||
}
|
||||
explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<FooBarContainer> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FooBarContainer>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list = 0,
|
||||
bool initialized = false,
|
||||
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
|
||||
flatbuffers::Offset<flatbuffers::String> location = 0) {
|
||||
FooBarContainerBuilder builder_(_fbb);
|
||||
builder_.add_location(location);
|
||||
builder_.add_list(list);
|
||||
builder_.add_fruit(fruit);
|
||||
builder_.add_initialized(initialized);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainerDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list = nullptr,
|
||||
bool initialized = false,
|
||||
benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples,
|
||||
const char *location = nullptr) {
|
||||
auto list__ = list ? _fbb.CreateVector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list) : 0;
|
||||
auto location__ = location ? _fbb.CreateString(location) : 0;
|
||||
return benchmarks_flatbuffers::CreateFooBarContainer(
|
||||
_fbb,
|
||||
list__,
|
||||
initialized,
|
||||
fruit,
|
||||
location__);
|
||||
}
|
||||
|
||||
inline const benchmarks_flatbuffers::FooBarContainer *GetFooBarContainer(const void *buf) {
|
||||
return flatbuffers::GetRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
|
||||
}
|
||||
|
||||
inline const benchmarks_flatbuffers::FooBarContainer *GetSizePrefixedFooBarContainer(const void *buf) {
|
||||
return flatbuffers::GetSizePrefixedRoot<benchmarks_flatbuffers::FooBarContainer>(buf);
|
||||
}
|
||||
|
||||
inline bool VerifyFooBarContainerBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
|
||||
}
|
||||
|
||||
inline bool VerifySizePrefixedFooBarContainerBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr);
|
||||
}
|
||||
|
||||
inline void FinishFooBarContainerBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline void FinishSizePrefixedFooBarContainerBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) {
|
||||
fbb.FinishSizePrefixed(root);
|
||||
}
|
||||
|
||||
} // namespace benchmarks_flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_
|
||||
80
benchmarks/cpp/flatbuffers/fb_bench.cpp
Normal file
80
benchmarks/cpp/flatbuffers/fb_bench.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "benchmarks/cpp/bench.h"
|
||||
#include "benchmarks/cpp/flatbuffers/bench_generated.h"
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
using namespace flatbuffers;
|
||||
using namespace benchmarks_flatbuffers;
|
||||
|
||||
namespace {
|
||||
|
||||
struct FlatBufferBench : Bench {
|
||||
explicit FlatBufferBench(int64_t initial_size, Allocator *allocator)
|
||||
: fbb(initial_size, allocator, false) {}
|
||||
|
||||
uint8_t *Encode(void *, int64_t &len) {
|
||||
fbb.Clear();
|
||||
|
||||
const int kVectorLength = 3;
|
||||
Offset<FooBar> vec[kVectorLength];
|
||||
|
||||
for (int i = 0; i < kVectorLength; ++i) {
|
||||
Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i);
|
||||
Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i);
|
||||
auto name = fbb.CreateString("Hello, World!");
|
||||
auto foobar =
|
||||
CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i, '!' + i);
|
||||
vec[i] = foobar;
|
||||
}
|
||||
auto location = fbb.CreateString("http://google.com/flatbuffers/");
|
||||
auto foobarvec = fbb.CreateVector(vec, kVectorLength);
|
||||
auto foobarcontainer =
|
||||
CreateFooBarContainer(fbb, foobarvec, true, Enum_Bananas, location);
|
||||
fbb.Finish(foobarcontainer);
|
||||
|
||||
len = fbb.GetSize();
|
||||
return fbb.GetBufferPointer();
|
||||
}
|
||||
|
||||
int64_t Use(void *decoded) {
|
||||
sum = 0;
|
||||
auto foobarcontainer = GetFooBarContainer(decoded);
|
||||
sum = 0;
|
||||
Add(foobarcontainer->initialized());
|
||||
Add(foobarcontainer->location()->Length());
|
||||
Add(foobarcontainer->fruit());
|
||||
for (unsigned int i = 0; i < foobarcontainer->list()->Length(); i++) {
|
||||
auto foobar = foobarcontainer->list()->Get(i);
|
||||
Add(foobar->name()->Length());
|
||||
Add(foobar->postfix());
|
||||
Add(static_cast<int64_t>(foobar->rating()));
|
||||
auto bar = foobar->sibling();
|
||||
Add(static_cast<int64_t>(bar->ratio()));
|
||||
Add(bar->size());
|
||||
Add(bar->time());
|
||||
auto &foo = bar->parent();
|
||||
Add(foo.count());
|
||||
Add(foo.id());
|
||||
Add(foo.length());
|
||||
Add(foo.prefix());
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void *Decode(void *buffer, int64_t) { return buffer; }
|
||||
void Dealloc(void *) override{};
|
||||
|
||||
FlatBufferBuilder fbb;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Bench> NewFlatBuffersBench(int64_t initial_size,
|
||||
Allocator *allocator) {
|
||||
return std::unique_ptr<FlatBufferBench>(
|
||||
new FlatBufferBench(initial_size, allocator));
|
||||
}
|
||||
23
benchmarks/cpp/flatbuffers/fb_bench.h
Normal file
23
benchmarks/cpp/flatbuffers/fb_bench.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
||||
#define BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "benchmarks/cpp/bench.h"
|
||||
#include "include/flatbuffers/flatbuffers.h"
|
||||
|
||||
struct StaticAllocator : public flatbuffers::Allocator {
|
||||
explicit StaticAllocator(uint8_t *buffer) : buffer_(buffer) {}
|
||||
|
||||
uint8_t *allocate(size_t) override { return buffer_; }
|
||||
|
||||
void deallocate(uint8_t *, size_t) override {}
|
||||
|
||||
uint8_t *buffer_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Bench> NewFlatBuffersBench(
|
||||
int64_t initial_size = 1024, flatbuffers::Allocator *allocator = nullptr);
|
||||
|
||||
#endif // BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
|
||||
109
benchmarks/cpp/raw/raw_bench.cpp
Normal file
109
benchmarks/cpp/raw/raw_bench.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "benchmarks/cpp/raw/raw_bench.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "benchmarks/cpp/bench.h"
|
||||
|
||||
namespace {
|
||||
const int64_t kStringLength = 32;
|
||||
const int64_t kVectorLength = 3;
|
||||
|
||||
enum Enum { Apples, Pears, Bananas };
|
||||
|
||||
struct Foo {
|
||||
int64_t id;
|
||||
short count;
|
||||
char prefix;
|
||||
int length;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
Foo parent;
|
||||
int time;
|
||||
float ratio;
|
||||
unsigned short size;
|
||||
};
|
||||
|
||||
struct FooBar {
|
||||
Bar sibling;
|
||||
// We have to stick this in, otherwise strlen() will make it slower than
|
||||
// FlatBuffers:
|
||||
int name_len;
|
||||
char name[kStringLength];
|
||||
double rating;
|
||||
unsigned char postfix;
|
||||
};
|
||||
|
||||
struct FooBarContainer {
|
||||
FooBar list[kVectorLength]; // 3 copies of the above
|
||||
bool initialized;
|
||||
Enum fruit;
|
||||
int location_len;
|
||||
char location[kStringLength];
|
||||
};
|
||||
|
||||
struct RawBench : Bench {
|
||||
uint8_t *Encode(void *buf, int64_t &len) {
|
||||
FooBarContainer *fbc = new (buf) FooBarContainer;
|
||||
strcpy(fbc->location, "http://google.com/flatbuffers/"); // Unsafe eek!
|
||||
fbc->location_len = (int)strlen(fbc->location);
|
||||
fbc->fruit = Bananas;
|
||||
fbc->initialized = true;
|
||||
for (int i = 0; i < kVectorLength; i++) {
|
||||
// We add + i to not make these identical copies for a more realistic
|
||||
// compression test.
|
||||
auto &foobar = fbc->list[i];
|
||||
foobar.rating = 3.1415432432445543543 + i;
|
||||
foobar.postfix = '!' + i;
|
||||
strcpy(foobar.name, "Hello, World!");
|
||||
foobar.name_len = (int)strlen(foobar.name);
|
||||
auto &bar = foobar.sibling;
|
||||
bar.ratio = 3.14159f + i;
|
||||
bar.size = 10000 + i;
|
||||
bar.time = 123456 + i;
|
||||
auto &foo = bar.parent;
|
||||
foo.id = 0xABADCAFEABADCAFE + i;
|
||||
foo.count = 10000 + i;
|
||||
foo.length = 1000000 + i;
|
||||
foo.prefix = '@' + i;
|
||||
}
|
||||
|
||||
len = sizeof(FooBarContainer);
|
||||
return reinterpret_cast<uint8_t *>(fbc);
|
||||
};
|
||||
|
||||
int64_t Use(void *decoded) {
|
||||
auto foobarcontainer = reinterpret_cast<FooBarContainer *>(decoded);
|
||||
sum = 0;
|
||||
Add(foobarcontainer->initialized);
|
||||
Add(foobarcontainer->location_len);
|
||||
Add(foobarcontainer->fruit);
|
||||
for (unsigned int i = 0; i < kVectorLength; i++) {
|
||||
auto foobar = &foobarcontainer->list[i];
|
||||
Add(foobar->name_len);
|
||||
Add(foobar->postfix);
|
||||
Add(static_cast<int64_t>(foobar->rating));
|
||||
auto bar = &foobar->sibling;
|
||||
Add(static_cast<int64_t>(bar->ratio));
|
||||
Add(bar->size);
|
||||
Add(bar->time);
|
||||
auto &foo = bar->parent;
|
||||
Add(foo.count);
|
||||
Add(foo.id);
|
||||
Add(foo.length);
|
||||
Add(foo.prefix);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void *Decode(void *buf, int64_t) { return buf; }
|
||||
void Dealloc(void *) override{};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Bench> NewRawBench() {
|
||||
return std::unique_ptr<RawBench>(new RawBench());
|
||||
}
|
||||
10
benchmarks/cpp/raw/raw_bench.h
Normal file
10
benchmarks/cpp/raw/raw_bench.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||
#define BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "benchmarks/cpp/bench.h"
|
||||
|
||||
std::unique_ptr<Bench> NewRawBench();
|
||||
|
||||
#endif // BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||
@@ -209,7 +209,7 @@ def flatbuffer_cc_library(
|
||||
Happy dependent Flatbuffering!
|
||||
'''
|
||||
output_headers = [
|
||||
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
|
||||
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1].split(":")[-1])
|
||||
for s in srcs
|
||||
]
|
||||
reflection_name = "%s_reflection" % name if gen_reflections else ""
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
# CHANGELOG
|
||||
## 2.0.0
|
||||
|
||||
- switch to null safety (#6696)
|
||||
- add Object APIs (pack/unpack) (#6682, #6723, #6846)
|
||||
- add custom builder buffer allocator support (#6711)
|
||||
- add `Builder.size()` - finished buffer size (#6403)
|
||||
- make `writeString()` argument non-nullable (#6737)
|
||||
- make tables fixed size (expect the number of fields when creating) (#6735)
|
||||
- make table deduplication optional (param `deduplicateTables`) (#6734)
|
||||
- change `Builder.reset()` to reuse an existing buffer (#6661)
|
||||
- change table building to assert() instead of exceptions (#6754)
|
||||
- optimize `writeString()` for ASCII (param `asciiOptimization`) (#6736)
|
||||
- change `StringReader` to make ASCII optimization optional (param `asciiOptimization`) (#6758)
|
||||
- change `[byte]` and `[ubyte]` representation to `dart:typed_data` `Int8List` and `Uint8List` (#6839)
|
||||
- rename `lowFinish()` to `buffer` getter (#6712)
|
||||
- fix `Builder._writeString()` - always write trailing zero byte (#6390)
|
||||
- fix `Builder.reset()` - clear vTables (#6386)
|
||||
- make sure added padding is zeroed, same as in C++ (#6716)
|
||||
- many performance improvements (#6755)
|
||||
|
||||
## 1.9.2
|
||||
|
||||
@@ -11,4 +29,4 @@
|
||||
|
||||
## 1.9.0
|
||||
|
||||
- Initial release, supports Dart 1.x and many dev versions of Dart 2.x
|
||||
- Initial release, supports Dart 1.x and many dev versions of Dart 2.x
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
# FlatBuffers for Dart
|
||||
|
||||
This package is used to read and write FlatBuffer files in Dart.
|
||||
This package is used to read and write [FlatBuffers](https://google.github.io/flatbuffers/).
|
||||
|
||||
Most consumers will want to use the [`flatc`](https://github.com/google/flatbuffers)
|
||||
compiler to generate Dart code from a FlatBuffers IDL schema. For example, the
|
||||
`monster_my_game.sample_generated.dart` was generated with `flatc` from
|
||||
`monster.fbs` in the example folder. The generated classes can be used to read
|
||||
or write binary files that are interoperable with other languages and platforms
|
||||
supported by FlatBuffers, as illustrated in the `example.dart` in the
|
||||
Most consumers will want to use the [`flatc` - FlatBuffer compiler](https://github.com/google/flatbuffers) binary for your platform:
|
||||
* [Linux](https://github.com/google/flatbuffers/suites/4363603985/artifacts/114682272)
|
||||
* [macOS](https://github.com/google/flatbuffers/suites/4363603985/artifacts/114682273)
|
||||
* [Windows](https://github.com/google/flatbuffers/suites/4363603985/artifacts/114682274)
|
||||
|
||||
The FlatBuffer compiler `flatc` reads a FlatBuffers IDL schema and generates Dart code.
|
||||
The generated classes can be used to read or write binary data/files that are interoperable with
|
||||
other languages and platforms supported by FlatBuffers, as illustrated in the `example.dart` in the
|
||||
examples folder.
|
||||
|
||||
Additional documentation and examples are available [at the FlatBuffers site](https://google.github.io/flatbuffers/index.html)
|
||||
For more details and documentation, head over to the official site and read the
|
||||
[Tutorial](https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html) and how to
|
||||
[use FlatBuffers in Dart](https://google.github.io/flatbuffers/flatbuffers_guide_use_dart.html).
|
||||
1
dart/analysis_options.yaml
Normal file
1
dart/analysis_options.yaml
Normal file
@@ -0,0 +1 @@
|
||||
include: package:lints/recommended.yaml
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_my_game.sample_generated.dart' as myGame;
|
||||
import './monster_my_game.sample_generated.dart' as my_game;
|
||||
|
||||
// Example how to use FlatBuffers to create and read binary buffers.
|
||||
|
||||
@@ -25,27 +25,27 @@ void main() {
|
||||
}
|
||||
|
||||
void builderTest() {
|
||||
final builder = new fb.Builder(initialSize: 1024);
|
||||
final int weaponOneName = builder.writeString("Sword");
|
||||
final builder = fb.Builder(initialSize: 1024);
|
||||
final int? weaponOneName = builder.writeString("Sword");
|
||||
final int weaponOneDamage = 3;
|
||||
|
||||
final int weaponTwoName = builder.writeString("Axe");
|
||||
final int? weaponTwoName = builder.writeString("Axe");
|
||||
final int weaponTwoDamage = 5;
|
||||
|
||||
final swordBuilder = new myGame.WeaponBuilder(builder)
|
||||
final swordBuilder = my_game.WeaponBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(weaponOneName)
|
||||
..addDamage(weaponOneDamage);
|
||||
final int sword = swordBuilder.finish();
|
||||
|
||||
final axeBuilder = new myGame.WeaponBuilder(builder)
|
||||
final axeBuilder = my_game.WeaponBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(weaponTwoName)
|
||||
..addDamage(weaponTwoDamage);
|
||||
final int axe = axeBuilder.finish();
|
||||
|
||||
// Serialize a name for our monster, called "Orc".
|
||||
final int name = builder.writeString('Orc');
|
||||
final int? name = builder.writeString('Orc');
|
||||
|
||||
// Create a list representing the inventory of the Orc. Each number
|
||||
// could correspond to an item that can be claimed after he is slain.
|
||||
@@ -54,7 +54,7 @@ void builderTest() {
|
||||
final weapons = builder.writeList([sword, axe]);
|
||||
|
||||
// Struct builders are very easy to reuse.
|
||||
final vec3Builder = new myGame.Vec3Builder(builder);
|
||||
final vec3Builder = my_game.Vec3Builder(builder);
|
||||
|
||||
vec3Builder.finish(4.0, 5.0, 6.0);
|
||||
vec3Builder.finish(1.0, 2.0, 3.0);
|
||||
@@ -62,21 +62,21 @@ void builderTest() {
|
||||
final int hp = 300;
|
||||
final int mana = 150;
|
||||
|
||||
final monster = new myGame.MonsterBuilder(builder)
|
||||
final monster = my_game.MonsterBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(name)
|
||||
..addInventoryOffset(inventory)
|
||||
..addWeaponsOffset(weapons)
|
||||
..addEquippedType(myGame.EquipmentTypeId.Weapon)
|
||||
..addEquippedType(my_game.EquipmentTypeId.Weapon)
|
||||
..addEquippedOffset(axe)
|
||||
..addHp(hp)
|
||||
..addMana(mana)
|
||||
..addPos(vec3Builder.finish(1.0, 2.0, 3.0))
|
||||
..addColor(myGame.Color.Red);
|
||||
..addColor(my_game.Color.Red);
|
||||
|
||||
final int monsteroff = monster.finish();
|
||||
final buffer = builder.finish(monsteroff);
|
||||
if (verify(buffer)) {
|
||||
builder.finish(monsteroff);
|
||||
if (verify(builder.buffer)) {
|
||||
print(
|
||||
"The FlatBuffer was successfully created with a builder and verified!");
|
||||
}
|
||||
@@ -85,17 +85,17 @@ void builderTest() {
|
||||
void objectBuilderTest() {
|
||||
// Create the builder here so we can use it for both weapons and equipped
|
||||
// the actual data will only be written to the buffer once.
|
||||
var axe = new myGame.WeaponObjectBuilder(name: 'Axe', damage: 5);
|
||||
var axe = my_game.WeaponObjectBuilder(name: 'Axe', damage: 5);
|
||||
|
||||
var monsterBuilder = new myGame.MonsterObjectBuilder(
|
||||
pos: new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
|
||||
var monsterBuilder = my_game.MonsterObjectBuilder(
|
||||
pos: my_game.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
|
||||
mana: 150,
|
||||
hp: 300,
|
||||
name: 'Orc',
|
||||
inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
color: myGame.Color.Red,
|
||||
weapons: [new myGame.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
|
||||
equippedType: myGame.EquipmentTypeId.Weapon,
|
||||
color: my_game.Color.Red,
|
||||
weapons: [my_game.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
|
||||
equippedType: my_game.EquipmentTypeId.Weapon,
|
||||
equipped: axe,
|
||||
);
|
||||
|
||||
@@ -114,7 +114,7 @@ void objectBuilderTest() {
|
||||
|
||||
bool verify(List<int> buffer) {
|
||||
// Get access to the root:
|
||||
var monster = new myGame.Monster(buffer);
|
||||
var monster = my_game.Monster(buffer);
|
||||
|
||||
// Get and test some scalar types from the FlatBuffer.
|
||||
assert(monster.hp == 80);
|
||||
@@ -122,31 +122,29 @@ bool verify(List<int> buffer) {
|
||||
assert(monster.name == "MyMonster");
|
||||
|
||||
// Get and test a field of the FlatBuffer's `struct`.
|
||||
var pos = monster.pos;
|
||||
assert(pos != null);
|
||||
var pos = monster.pos!;
|
||||
assert(pos.z == 3.0);
|
||||
|
||||
// Get a test an element from the `inventory` FlatBuffer's `vector`.
|
||||
var inv = monster.inventory;
|
||||
assert(inv != null);
|
||||
var inv = monster.inventory!;
|
||||
assert(inv.length == 10);
|
||||
assert(inv[9] == 9);
|
||||
|
||||
// Get and test the `weapons` FlatBuffers's `vector`.
|
||||
var expected_weapon_names = ["Sword", "Axe"];
|
||||
var expected_weapon_damages = [3, 5];
|
||||
var weps = monster.weapons;
|
||||
var expectedWeaponNames = ["Sword", "Axe"];
|
||||
var expectedWeaponDamages = [3, 5];
|
||||
var weps = monster.weapons!;
|
||||
for (int i = 0; i < weps.length; i++) {
|
||||
assert(weps[i].name == expected_weapon_names[i]);
|
||||
assert(weps[i].damage == expected_weapon_damages[i]);
|
||||
assert(weps[i].name == expectedWeaponNames[i]);
|
||||
assert(weps[i].damage == expectedWeaponDamages[i]);
|
||||
}
|
||||
|
||||
// Get and test the `Equipment` union (`equipped` field).
|
||||
assert(monster.equippedType.value == myGame.EquipmentTypeId.Weapon.value);
|
||||
assert(monster.equippedType == myGame.EquipmentTypeId.Weapon);
|
||||
assert(monster.equippedType!.value == my_game.EquipmentTypeId.Weapon.value);
|
||||
assert(monster.equippedType == my_game.EquipmentTypeId.Weapon);
|
||||
|
||||
assert(monster.equipped is myGame.Weapon);
|
||||
var equipped = monster.equipped as myGame.Weapon;
|
||||
assert(monster.equipped is my_game.Weapon);
|
||||
var equipped = monster.equipped as my_game.Weapon;
|
||||
assert(equipped.name == "Axe");
|
||||
assert(equipped.damage == 5);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
library my_game.sample;
|
||||
|
||||
@@ -12,23 +12,29 @@ class Color {
|
||||
const Color._(this.value);
|
||||
|
||||
factory Color.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum Color');
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum Color');
|
||||
}
|
||||
return values[value];
|
||||
return result;
|
||||
}
|
||||
|
||||
static Color? _createOrNull(int? value) =>
|
||||
value == null ? null : Color.fromValue(value);
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 2;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Color Red = const Color._(0);
|
||||
static const Color Green = const Color._(1);
|
||||
static const Color Blue = const Color._(2);
|
||||
static const Map<int,Color> values = {0: Red,1: Green,2: Blue,};
|
||||
static const Color Red = Color._(0);
|
||||
static const Color Green = Color._(1);
|
||||
static const Color Blue = Color._(2);
|
||||
static const Map<int, Color> values = {
|
||||
0: Red,
|
||||
1: Green,
|
||||
2: Blue};
|
||||
|
||||
static const fb.Reader<Color> reader = const _ColorReader();
|
||||
static const fb.Reader<Color> reader = _ColorReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -44,7 +50,7 @@ class _ColorReader extends fb.Reader<Color> {
|
||||
|
||||
@override
|
||||
Color read(fb.BufferContext bc, int offset) =>
|
||||
new Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class EquipmentTypeId {
|
||||
@@ -52,22 +58,27 @@ class EquipmentTypeId {
|
||||
const EquipmentTypeId._(this.value);
|
||||
|
||||
factory EquipmentTypeId.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum EquipmentTypeId');
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum EquipmentTypeId');
|
||||
}
|
||||
return values[value];
|
||||
return result;
|
||||
}
|
||||
|
||||
static EquipmentTypeId? _createOrNull(int? value) =>
|
||||
value == null ? null : EquipmentTypeId.fromValue(value);
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 1;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const EquipmentTypeId NONE = const EquipmentTypeId._(0);
|
||||
static const EquipmentTypeId Weapon = const EquipmentTypeId._(1);
|
||||
static const Map<int,EquipmentTypeId> values = {0: NONE,1: Weapon,};
|
||||
static const EquipmentTypeId NONE = EquipmentTypeId._(0);
|
||||
static const EquipmentTypeId Weapon = EquipmentTypeId._(1);
|
||||
static const Map<int, EquipmentTypeId> values = {
|
||||
0: NONE,
|
||||
1: Weapon};
|
||||
|
||||
static const fb.Reader<EquipmentTypeId> reader = const _EquipmentTypeIdReader();
|
||||
static const fb.Reader<EquipmentTypeId> reader = _EquipmentTypeIdReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -83,13 +94,13 @@ class _EquipmentTypeIdReader extends fb.Reader<EquipmentTypeId> {
|
||||
|
||||
@override
|
||||
EquipmentTypeId read(fb.BufferContext bc, int offset) =>
|
||||
new EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Vec3 {
|
||||
Vec3._(this._bc, this._bcOffset);
|
||||
|
||||
static const fb.Reader<Vec3> reader = const _Vec3Reader();
|
||||
static const fb.Reader<Vec3> reader = _Vec3Reader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
@@ -112,13 +123,11 @@ class _Vec3Reader extends fb.StructReader<Vec3> {
|
||||
|
||||
@override
|
||||
Vec3 createObject(fb.BufferContext bc, int offset) =>
|
||||
new Vec3._(bc, offset);
|
||||
Vec3._(bc, offset);
|
||||
}
|
||||
|
||||
class Vec3Builder {
|
||||
Vec3Builder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
Vec3Builder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
@@ -137,9 +146,9 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
final double _z;
|
||||
|
||||
Vec3ObjectBuilder({
|
||||
double x,
|
||||
double y,
|
||||
double z,
|
||||
required double x,
|
||||
required double y,
|
||||
required double z,
|
||||
})
|
||||
: _x = x,
|
||||
_y = y,
|
||||
@@ -147,10 +156,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.putFloat32(_z);
|
||||
fbBuilder.putFloat32(_y);
|
||||
fbBuilder.putFloat32(_x);
|
||||
@@ -159,39 +165,39 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class Monster {
|
||||
Monster._(this._bc, this._bcOffset);
|
||||
factory Monster(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||
static const fb.Reader<Monster> reader = _MonsterReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
Vec3 get pos => Vec3.reader.vTableGet(_bc, _bcOffset, 4, null);
|
||||
Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4);
|
||||
int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150);
|
||||
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null);
|
||||
List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null);
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
|
||||
List<Weapon> get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGet(_bc, _bcOffset, 18, null);
|
||||
EquipmentTypeId get equippedType => new EquipmentTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 20, 0));
|
||||
String? get name => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10);
|
||||
List<int>? get inventory => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14);
|
||||
Color get color => Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
|
||||
List<Weapon>? get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGetNullable(_bc, _bcOffset, 18);
|
||||
EquipmentTypeId? get equippedType => EquipmentTypeId._createOrNull(const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 20));
|
||||
dynamic get equipped {
|
||||
switch (equippedType?.value) {
|
||||
case 1: return Weapon.reader.vTableGet(_bc, _bcOffset, 22, null);
|
||||
case 1: return Weapon.reader.vTableGetNullable(_bc, _bcOffset, 22);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
List<Vec3> get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGet(_bc, _bcOffset, 24, null);
|
||||
List<Vec3>? get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGetNullable(_bc, _bcOffset, 24);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -204,57 +210,55 @@ class _MonsterReader extends fb.TableReader<Monster> {
|
||||
|
||||
@override
|
||||
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||
new Monster._(bc, offset);
|
||||
Monster._(bc, offset);
|
||||
}
|
||||
|
||||
class MonsterBuilder {
|
||||
MonsterBuilder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
MonsterBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable();
|
||||
fbBuilder.startTable(10);
|
||||
}
|
||||
|
||||
int addPos(int offset) {
|
||||
fbBuilder.addStruct(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addMana(int mana) {
|
||||
int addMana(int? mana) {
|
||||
fbBuilder.addInt16(1, mana);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addHp(int hp) {
|
||||
int addHp(int? hp) {
|
||||
fbBuilder.addInt16(2, hp);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNameOffset(int offset) {
|
||||
int addNameOffset(int? offset) {
|
||||
fbBuilder.addOffset(3, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addInventoryOffset(int offset) {
|
||||
int addInventoryOffset(int? offset) {
|
||||
fbBuilder.addOffset(5, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addColor(Color color) {
|
||||
int addColor(Color? color) {
|
||||
fbBuilder.addInt8(6, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addWeaponsOffset(int offset) {
|
||||
int addWeaponsOffset(int? offset) {
|
||||
fbBuilder.addOffset(7, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addEquippedType(EquipmentTypeId equippedType) {
|
||||
int addEquippedType(EquipmentTypeId? equippedType) {
|
||||
fbBuilder.addUint8(8, equippedType?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addEquippedOffset(int offset) {
|
||||
int addEquippedOffset(int? offset) {
|
||||
fbBuilder.addOffset(9, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addPathOffset(int offset) {
|
||||
int addPathOffset(int? offset) {
|
||||
fbBuilder.addOffset(10, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
@@ -265,28 +269,28 @@ class MonsterBuilder {
|
||||
}
|
||||
|
||||
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final Vec3ObjectBuilder _pos;
|
||||
final int _mana;
|
||||
final int _hp;
|
||||
final String _name;
|
||||
final List<int> _inventory;
|
||||
final Color _color;
|
||||
final List<WeaponObjectBuilder> _weapons;
|
||||
final EquipmentTypeId _equippedType;
|
||||
final Vec3ObjectBuilder? _pos;
|
||||
final int? _mana;
|
||||
final int? _hp;
|
||||
final String? _name;
|
||||
final List<int>? _inventory;
|
||||
final Color? _color;
|
||||
final List<WeaponObjectBuilder>? _weapons;
|
||||
final EquipmentTypeId? _equippedType;
|
||||
final dynamic _equipped;
|
||||
final List<Vec3ObjectBuilder> _path;
|
||||
final List<Vec3ObjectBuilder>? _path;
|
||||
|
||||
MonsterObjectBuilder({
|
||||
Vec3ObjectBuilder pos,
|
||||
int mana,
|
||||
int hp,
|
||||
String name,
|
||||
List<int> inventory,
|
||||
Color color,
|
||||
List<WeaponObjectBuilder> weapons,
|
||||
EquipmentTypeId equippedType,
|
||||
Vec3ObjectBuilder? pos,
|
||||
int? mana,
|
||||
int? hp,
|
||||
String? name,
|
||||
List<int>? inventory,
|
||||
Color? color,
|
||||
List<WeaponObjectBuilder>? weapons,
|
||||
EquipmentTypeId? equippedType,
|
||||
dynamic equipped,
|
||||
List<Vec3ObjectBuilder> path,
|
||||
List<Vec3ObjectBuilder>? path,
|
||||
})
|
||||
: _pos = pos,
|
||||
_mana = mana,
|
||||
@@ -301,68 +305,53 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
final int nameOffset = fbBuilder.writeString(_name);
|
||||
final int inventoryOffset = _inventory?.isNotEmpty == true
|
||||
? fbBuilder.writeListUint8(_inventory)
|
||||
: null;
|
||||
final int weaponsOffset = _weapons?.isNotEmpty == true
|
||||
? fbBuilder.writeList(_weapons.map((b) => b.getOrCreateOffset(fbBuilder)).toList())
|
||||
: null;
|
||||
final int equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
|
||||
final int pathOffset = _path?.isNotEmpty == true
|
||||
? fbBuilder.writeListOfStructs(_path)
|
||||
: null;
|
||||
|
||||
fbBuilder.startTable();
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
final int? nameOffset = _name == null ? null
|
||||
: fbBuilder.writeString(_name!);
|
||||
final int? inventoryOffset = _inventory == null ? null
|
||||
: fbBuilder.writeListUint8(_inventory!);
|
||||
final int? weaponsOffset = _weapons == null ? null
|
||||
: fbBuilder.writeList(_weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList());
|
||||
final int? equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
|
||||
final int? pathOffset = _path == null ? null
|
||||
: fbBuilder.writeListOfStructs(_path!);
|
||||
fbBuilder.startTable(10);
|
||||
if (_pos != null) {
|
||||
fbBuilder.addStruct(0, _pos.finish(fbBuilder));
|
||||
fbBuilder.addStruct(0, _pos!.finish(fbBuilder));
|
||||
}
|
||||
fbBuilder.addInt16(1, _mana);
|
||||
fbBuilder.addInt16(2, _hp);
|
||||
if (nameOffset != null) {
|
||||
fbBuilder.addOffset(3, nameOffset);
|
||||
}
|
||||
if (inventoryOffset != null) {
|
||||
fbBuilder.addOffset(5, inventoryOffset);
|
||||
}
|
||||
fbBuilder.addOffset(3, nameOffset);
|
||||
fbBuilder.addOffset(5, inventoryOffset);
|
||||
fbBuilder.addInt8(6, _color?.value);
|
||||
if (weaponsOffset != null) {
|
||||
fbBuilder.addOffset(7, weaponsOffset);
|
||||
}
|
||||
fbBuilder.addOffset(7, weaponsOffset);
|
||||
fbBuilder.addUint8(8, _equippedType?.value);
|
||||
if (equippedOffset != null) {
|
||||
fbBuilder.addOffset(9, equippedOffset);
|
||||
}
|
||||
if (pathOffset != null) {
|
||||
fbBuilder.addOffset(10, pathOffset);
|
||||
}
|
||||
fbBuilder.addOffset(9, equippedOffset);
|
||||
fbBuilder.addOffset(10, pathOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class Weapon {
|
||||
Weapon._(this._bc, this._bcOffset);
|
||||
factory Weapon(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Weapon> reader = const _WeaponReader();
|
||||
static const fb.Reader<Weapon> reader = _WeaponReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 4, null);
|
||||
String? get name => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4);
|
||||
int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 0);
|
||||
|
||||
@override
|
||||
@@ -376,25 +365,23 @@ class _WeaponReader extends fb.TableReader<Weapon> {
|
||||
|
||||
@override
|
||||
Weapon createObject(fb.BufferContext bc, int offset) =>
|
||||
new Weapon._(bc, offset);
|
||||
Weapon._(bc, offset);
|
||||
}
|
||||
|
||||
class WeaponBuilder {
|
||||
WeaponBuilder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
WeaponBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable();
|
||||
fbBuilder.startTable(2);
|
||||
}
|
||||
|
||||
int addNameOffset(int offset) {
|
||||
int addNameOffset(int? offset) {
|
||||
fbBuilder.addOffset(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addDamage(int damage) {
|
||||
int addDamage(int? damage) {
|
||||
fbBuilder.addInt16(1, damage);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
@@ -405,36 +392,32 @@ class WeaponBuilder {
|
||||
}
|
||||
|
||||
class WeaponObjectBuilder extends fb.ObjectBuilder {
|
||||
final String _name;
|
||||
final int _damage;
|
||||
final String? _name;
|
||||
final int? _damage;
|
||||
|
||||
WeaponObjectBuilder({
|
||||
String name,
|
||||
int damage,
|
||||
String? name,
|
||||
int? damage,
|
||||
})
|
||||
: _name = name,
|
||||
_damage = damage;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
final int nameOffset = fbBuilder.writeString(_name);
|
||||
|
||||
fbBuilder.startTable();
|
||||
if (nameOffset != null) {
|
||||
fbBuilder.addOffset(0, nameOffset);
|
||||
}
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
final int? nameOffset = _name == null ? null
|
||||
: fbBuilder.writeString(_name!);
|
||||
fbBuilder.startTable(2);
|
||||
fbBuilder.addOffset(0, nameOffset);
|
||||
fbBuilder.addInt16(1, _damage);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,38 +5,27 @@ import 'types.dart';
|
||||
|
||||
/// The main builder class for creation of a FlexBuffer.
|
||||
class Builder {
|
||||
ByteData _buffer;
|
||||
List<_StackValue> _stack;
|
||||
List<_StackPointer> _stackPointers;
|
||||
int _offset;
|
||||
bool _finished;
|
||||
Map<String, _StackValue> _stringCache;
|
||||
Map<String, _StackValue> _keyCache;
|
||||
Map<_KeysHash, _StackValue> _keyVectorCache;
|
||||
Map<int, _StackValue> _indirectIntCache;
|
||||
Map<double, _StackValue> _indirectDoubleCache;
|
||||
final ByteData _buffer;
|
||||
List<_StackValue> _stack = [];
|
||||
List<_StackPointer> _stackPointers = [];
|
||||
int _offset = 0;
|
||||
bool _finished = false;
|
||||
final Map<String, _StackValue> _stringCache = {};
|
||||
final Map<String, _StackValue> _keyCache = {};
|
||||
final Map<_KeysHash, _StackValue> _keyVectorCache = {};
|
||||
final Map<int, _StackValue> _indirectIntCache = {};
|
||||
final Map<double, _StackValue> _indirectDoubleCache = {};
|
||||
|
||||
/// Instantiate the builder if you intent to gradually build up the buffer by calling
|
||||
/// add... methods and calling [finish] to receive the the resulting byte array.
|
||||
///
|
||||
/// The default size of internal buffer is set to 2048. Provide a different value in order to avoid buffer copies.
|
||||
Builder({int size = 2048}) {
|
||||
_buffer = ByteData(size);
|
||||
_stack = [];
|
||||
_stackPointers = [];
|
||||
_offset = 0;
|
||||
_finished = false;
|
||||
_stringCache = {};
|
||||
_keyCache = {};
|
||||
_keyVectorCache = {};
|
||||
_indirectIntCache = {};
|
||||
_indirectDoubleCache = {};
|
||||
}
|
||||
Builder({int size = 2048}) : _buffer = ByteData(size);
|
||||
|
||||
/// Use this method in order to turn an object into a FlexBuffer directly.
|
||||
///
|
||||
/// Use the manual instantiation of the [Builder] and gradual addition of values, if performance is more important than convenience.
|
||||
static ByteBuffer buildFromObject(Object value) {
|
||||
static ByteBuffer buildFromObject(Object? value) {
|
||||
final builder = Builder();
|
||||
builder._add(value);
|
||||
final buffer = builder.finish();
|
||||
@@ -45,7 +34,7 @@ class Builder {
|
||||
return byteData.buffer;
|
||||
}
|
||||
|
||||
void _add(Object value) {
|
||||
void _add(Object? value) {
|
||||
if (value == null) {
|
||||
addNull();
|
||||
} else if (value is bool) {
|
||||
@@ -81,32 +70,32 @@ class Builder {
|
||||
/// Specifically useful when building up a vector where values can be null.
|
||||
void addNull() {
|
||||
_integrityCheckOnValueAddition();
|
||||
_stack.add(_StackValue.WithNull());
|
||||
_stack.add(_StackValue.withNull());
|
||||
}
|
||||
|
||||
/// Adds a string value.
|
||||
void addInt(int value) {
|
||||
_integrityCheckOnValueAddition();
|
||||
_stack.add(_StackValue.WithInt(value));
|
||||
_stack.add(_StackValue.withInt(value));
|
||||
}
|
||||
|
||||
/// Adds a bool value.
|
||||
void addBool(bool value) {
|
||||
_integrityCheckOnValueAddition();
|
||||
_stack.add(_StackValue.WithBool(value));
|
||||
_stack.add(_StackValue.withBool(value));
|
||||
}
|
||||
|
||||
/// Adds a double value.
|
||||
void addDouble(double value) {
|
||||
_integrityCheckOnValueAddition();
|
||||
_stack.add(_StackValue.WithDouble(value));
|
||||
_stack.add(_StackValue.withDouble(value));
|
||||
}
|
||||
|
||||
/// Adds a string value.
|
||||
void addString(String value) {
|
||||
_integrityCheckOnValueAddition();
|
||||
if (_stringCache.containsKey(value)) {
|
||||
_stack.add(_stringCache[value]);
|
||||
_stack.add(_stringCache[value]!);
|
||||
return;
|
||||
}
|
||||
final utf8String = utf8.encode(value);
|
||||
@@ -118,7 +107,8 @@ class Builder {
|
||||
final newOffset = _newOffset(length + 1);
|
||||
_pushBuffer(utf8String);
|
||||
_offset = newOffset;
|
||||
final stackValue = _StackValue.WithOffset(stringOffset, ValueType.String, bitWidth);
|
||||
final stackValue =
|
||||
_StackValue.withOffset(stringOffset, ValueType.String, bitWidth);
|
||||
_stack.add(stackValue);
|
||||
_stringCache[value] = stackValue;
|
||||
}
|
||||
@@ -129,7 +119,7 @@ class Builder {
|
||||
void addKey(String value) {
|
||||
_integrityCheckOnKeyAddition();
|
||||
if (_keyCache.containsKey(value)) {
|
||||
_stack.add(_keyCache[value]);
|
||||
_stack.add(_keyCache[value]!);
|
||||
return;
|
||||
}
|
||||
final utf8String = utf8.encode(value);
|
||||
@@ -138,7 +128,8 @@ class Builder {
|
||||
final newOffset = _newOffset(length + 1);
|
||||
_pushBuffer(utf8String);
|
||||
_offset = newOffset;
|
||||
final stackValue = _StackValue.WithOffset(keyOffset, ValueType.Key, BitWidth.width8);
|
||||
final stackValue =
|
||||
_StackValue.withOffset(keyOffset, ValueType.Key, BitWidth.width8);
|
||||
_stack.add(stackValue);
|
||||
_keyCache[value] = stackValue;
|
||||
}
|
||||
@@ -156,7 +147,8 @@ class Builder {
|
||||
final newOffset = _newOffset(length);
|
||||
_pushBuffer(value.asUint8List());
|
||||
_offset = newOffset;
|
||||
final stackValue = _StackValue.WithOffset(blobOffset, ValueType.Blob, bitWidth);
|
||||
final stackValue =
|
||||
_StackValue.withOffset(blobOffset, ValueType.Blob, bitWidth);
|
||||
_stack.add(stackValue);
|
||||
}
|
||||
|
||||
@@ -169,15 +161,16 @@ class Builder {
|
||||
void addIntIndirectly(int value, {bool cache = false}) {
|
||||
_integrityCheckOnValueAddition();
|
||||
if (_indirectIntCache.containsKey(value)) {
|
||||
_stack.add(_indirectIntCache[value]);
|
||||
_stack.add(_indirectIntCache[value]!);
|
||||
return;
|
||||
}
|
||||
final stackValue = _StackValue.WithInt(value);
|
||||
final stackValue = _StackValue.withInt(value);
|
||||
final byteWidth = _align(stackValue.width);
|
||||
final newOffset = _newOffset(byteWidth);
|
||||
final valueOffset = _offset;
|
||||
_pushBuffer(stackValue.asU8List(stackValue.width));
|
||||
final stackOffset = _StackValue.WithOffset(valueOffset, ValueType.IndirectInt, stackValue.width);
|
||||
final stackOffset = _StackValue.withOffset(
|
||||
valueOffset, ValueType.IndirectInt, stackValue.width);
|
||||
_stack.add(stackOffset);
|
||||
_offset = newOffset;
|
||||
if (cache) {
|
||||
@@ -193,15 +186,16 @@ class Builder {
|
||||
void addDoubleIndirectly(double value, {bool cache = false}) {
|
||||
_integrityCheckOnValueAddition();
|
||||
if (cache && _indirectDoubleCache.containsKey(value)) {
|
||||
_stack.add(_indirectDoubleCache[value]);
|
||||
_stack.add(_indirectDoubleCache[value]!);
|
||||
return;
|
||||
}
|
||||
final stackValue = _StackValue.WithDouble(value);
|
||||
final stackValue = _StackValue.withDouble(value);
|
||||
final byteWidth = _align(stackValue.width);
|
||||
final newOffset = _newOffset(byteWidth);
|
||||
final valueOffset = _offset;
|
||||
_pushBuffer(stackValue.asU8List(stackValue.width));
|
||||
final stackOffset = _StackValue.WithOffset(valueOffset, ValueType.IndirectFloat, stackValue.width);
|
||||
final stackOffset = _StackValue.withOffset(
|
||||
valueOffset, ValueType.IndirectFloat, stackValue.width);
|
||||
_stack.add(stackOffset);
|
||||
_offset = newOffset;
|
||||
if (cache) {
|
||||
@@ -258,8 +252,10 @@ class Builder {
|
||||
tmp._offset = _offset;
|
||||
tmp._stack = List.from(_stack);
|
||||
tmp._stackPointers = List.from(_stackPointers);
|
||||
tmp._buffer.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List(0, _offset));
|
||||
for (var i = 0; i < tmp._stackPointers.length; i++){
|
||||
tmp._buffer.buffer
|
||||
.asUint8List()
|
||||
.setAll(0, _buffer.buffer.asUint8List(0, _offset));
|
||||
for (var i = 0; i < tmp._stackPointers.length; i++) {
|
||||
tmp.end();
|
||||
}
|
||||
final buffer = tmp.finish();
|
||||
@@ -267,14 +263,15 @@ class Builder {
|
||||
bd.buffer.asUint8List().setAll(0, buffer);
|
||||
return bd.buffer;
|
||||
}
|
||||
|
||||
|
||||
void _integrityCheckOnValueAddition() {
|
||||
if (_finished) {
|
||||
throw StateError('Adding values after finish is prohibited');
|
||||
}
|
||||
if (_stackPointers.isNotEmpty && _stackPointers.last.isVector == false) {
|
||||
if (_stack.last.type != ValueType.Key) {
|
||||
throw StateError('Adding value to a map before adding a key is prohibited');
|
||||
throw StateError(
|
||||
'Adding value to a map before adding a key is prohibited');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,7 +287,8 @@ class Builder {
|
||||
|
||||
void _finish() {
|
||||
if (_stack.length != 1) {
|
||||
throw StateError('Stack has to be exactly 1, but is ${_stack.length}. You have to end all started vectors and maps, before calling [finish]');
|
||||
throw StateError(
|
||||
'Stack has to be exactly 1, but is ${_stack.length}. You have to end all started vectors and maps, before calling [finish]');
|
||||
}
|
||||
final value = _stack[0];
|
||||
final byteWidth = _align(value.elementWidth(_offset, 0));
|
||||
@@ -299,8 +297,9 @@ class Builder {
|
||||
_writeUInt(byteWidth, 1);
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
_StackValue _createVector(int start, int vecLength, int step, [_StackValue keys]) {
|
||||
|
||||
_StackValue _createVector(int start, int vecLength, int step,
|
||||
[_StackValue? keys]) {
|
||||
var bitWidth = BitWidthUtil.uwidth(vecLength);
|
||||
var prefixElements = 1;
|
||||
if (keys != null) {
|
||||
@@ -327,7 +326,9 @@ class Builder {
|
||||
}
|
||||
}
|
||||
final byteWidth = _align(bitWidth);
|
||||
final fix = typed & ValueTypeUtils.isNumber(vectorType) && vecLength >= 2 && vecLength <= 4;
|
||||
final fix = typed & ValueTypeUtils.isNumber(vectorType) &&
|
||||
vecLength >= 2 &&
|
||||
vecLength <= 4;
|
||||
if (keys != null) {
|
||||
_writeStackValue(keys, byteWidth);
|
||||
_writeUInt(1 << keys.width.index, byteWidth);
|
||||
@@ -345,13 +346,14 @@ class Builder {
|
||||
}
|
||||
}
|
||||
if (keys != null) {
|
||||
return _StackValue.WithOffset(vecOffset, ValueType.Map, bitWidth);
|
||||
return _StackValue.withOffset(vecOffset, ValueType.Map, bitWidth);
|
||||
}
|
||||
if (typed) {
|
||||
final vType = ValueTypeUtils.toTypedVector(vectorType, fix ? vecLength : 0);
|
||||
return _StackValue.WithOffset(vecOffset, vType, bitWidth);
|
||||
final vType =
|
||||
ValueTypeUtils.toTypedVector(vectorType, fix ? vecLength : 0);
|
||||
return _StackValue.withOffset(vecOffset, vType, bitWidth);
|
||||
}
|
||||
return _StackValue.WithOffset(vecOffset, ValueType.Vector, bitWidth);
|
||||
return _StackValue.withOffset(vecOffset, ValueType.Vector, bitWidth);
|
||||
}
|
||||
|
||||
void _endVector(_StackPointer pointer) {
|
||||
@@ -363,12 +365,13 @@ class Builder {
|
||||
|
||||
void _sortKeysAndEndMap(_StackPointer pointer) {
|
||||
if (((_stack.length - pointer.stackPosition) & 1) == 1) {
|
||||
throw StateError('The stack needs to hold key value pairs (even number of elements). Check if you combined [addKey] with add... method calls properly.');
|
||||
throw StateError(
|
||||
'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;
|
||||
for (var i = pointer.stackPosition; i < _stack.length - 2; i += 2) {
|
||||
if (_shouldFlip(_stack[i], _stack[i+2])) {
|
||||
if (_shouldFlip(_stack[i], _stack[i + 2])) {
|
||||
sorted = false;
|
||||
break;
|
||||
}
|
||||
@@ -394,36 +397,38 @@ class Builder {
|
||||
}
|
||||
_endMap(pointer);
|
||||
}
|
||||
|
||||
|
||||
void _endMap(_StackPointer pointer) {
|
||||
final vecLength = (_stack.length - pointer.stackPosition) >> 1;
|
||||
final offsets = <int>[];
|
||||
for (var i = pointer.stackPosition; i < _stack.length; i += 2) {
|
||||
offsets.add(_stack[i].offset);
|
||||
offsets.add(_stack[i].offset!);
|
||||
}
|
||||
final keysHash = _KeysHash(offsets);
|
||||
var keysStackValue;
|
||||
_StackValue? keysStackValue;
|
||||
if (_keyVectorCache.containsKey(keysHash)) {
|
||||
keysStackValue = _keyVectorCache[keysHash];
|
||||
} else {
|
||||
keysStackValue = _createVector(pointer.stackPosition, vecLength, 2);
|
||||
_keyVectorCache[keysHash] = keysStackValue;
|
||||
}
|
||||
final vec = _createVector(pointer.stackPosition + 1, vecLength, 2, keysStackValue);
|
||||
final vec =
|
||||
_createVector(pointer.stackPosition + 1, vecLength, 2, keysStackValue);
|
||||
_stack.removeRange(pointer.stackPosition, _stack.length);
|
||||
_stack.add(vec);
|
||||
}
|
||||
|
||||
bool _shouldFlip(_StackValue v1, _StackValue v2) {
|
||||
if (v1.type != ValueType.Key || v2.type != ValueType.Key) {
|
||||
throw StateError('Stack values are not keys $v1 | $v2. Check if you combined [addKey] with add... method calls properly.');
|
||||
throw StateError(
|
||||
'Stack values are not keys $v1 | $v2. Check if you combined [addKey] with add... method calls properly.');
|
||||
}
|
||||
|
||||
var c1, c2;
|
||||
late int c1, c2;
|
||||
var index = 0;
|
||||
do {
|
||||
c1 = _buffer.getUint8(v1.offset + index);
|
||||
c2 = _buffer.getUint8(v2.offset + index);
|
||||
c1 = _buffer.getUint8(v1.offset! + index);
|
||||
c2 = _buffer.getUint8(v2.offset! + index);
|
||||
if (c2 < c1) return true;
|
||||
if (c1 < c2) return false;
|
||||
index += 1;
|
||||
@@ -440,11 +445,12 @@ class Builder {
|
||||
void _writeStackValue(_StackValue value, int byteWidth) {
|
||||
final newOffset = _newOffset(byteWidth);
|
||||
if (value.isOffset) {
|
||||
final relativeOffset = _offset - value.offset;
|
||||
final relativeOffset = _offset - value.offset!;
|
||||
if (byteWidth == 8 || relativeOffset < (1 << (byteWidth * 8))) {
|
||||
_writeUInt(relativeOffset, byteWidth);
|
||||
} else {
|
||||
throw StateError('Unexpected size $byteWidth. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
|
||||
throw StateError(
|
||||
'Unexpected size $byteWidth. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
|
||||
}
|
||||
} else {
|
||||
_pushBuffer(value.asU8List(BitWidthUtil.fromByteWidth(byteWidth)));
|
||||
@@ -467,16 +473,13 @@ class Builder {
|
||||
}
|
||||
if (prevSize < size) {
|
||||
final newBuf = ByteData(size);
|
||||
newBuf.buffer
|
||||
.asUint8List()
|
||||
.setAll(0, _buffer.buffer.asUint8List());
|
||||
newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List());
|
||||
}
|
||||
return newOffset;
|
||||
}
|
||||
|
||||
void _pushInt(int value, BitWidth width) {
|
||||
switch (width) {
|
||||
|
||||
case BitWidth.width8:
|
||||
_buffer.setInt8(_offset, value);
|
||||
break;
|
||||
@@ -494,7 +497,6 @@ class Builder {
|
||||
|
||||
void _pushUInt(int value, BitWidth width) {
|
||||
switch (width) {
|
||||
|
||||
case BitWidth.width8:
|
||||
_buffer.setUint8(_offset, value);
|
||||
break;
|
||||
@@ -516,37 +518,39 @@ class Builder {
|
||||
}
|
||||
|
||||
class _StackValue {
|
||||
Object _value;
|
||||
int _offset;
|
||||
ValueType _type;
|
||||
BitWidth _width;
|
||||
_StackValue.WithNull() {
|
||||
_type = ValueType.Null;
|
||||
_width = BitWidth.width8;
|
||||
}
|
||||
_StackValue.WithInt(int value) {
|
||||
_type = value != null ? ValueType.Int : ValueType.Null;
|
||||
_width = BitWidthUtil.width(value);
|
||||
_value = value;
|
||||
}
|
||||
_StackValue.WithBool(bool value) {
|
||||
_type = value != null ? ValueType.Bool : ValueType.Null;
|
||||
_width = BitWidth.width8;
|
||||
_value = value;
|
||||
}
|
||||
_StackValue.WithDouble(double value) {
|
||||
_type = value != null ? ValueType.Float : ValueType.Null;
|
||||
_width = BitWidthUtil.width(value);
|
||||
_value = value;
|
||||
}
|
||||
_StackValue.WithOffset(int value, ValueType type, BitWidth width) {
|
||||
_offset = value;
|
||||
_type = type;
|
||||
_width = width;
|
||||
}
|
||||
late Object _value;
|
||||
int? _offset;
|
||||
final ValueType _type;
|
||||
final BitWidth _width;
|
||||
|
||||
_StackValue.withNull()
|
||||
: _type = ValueType.Null,
|
||||
_width = BitWidth.width8;
|
||||
|
||||
_StackValue.withInt(int value)
|
||||
: _type = ValueType.Int,
|
||||
_width = BitWidthUtil.width(value),
|
||||
_value = value;
|
||||
|
||||
_StackValue.withBool(bool value)
|
||||
: _type = ValueType.Bool,
|
||||
_width = BitWidth.width8,
|
||||
_value = value;
|
||||
|
||||
_StackValue.withDouble(double value)
|
||||
: _type = ValueType.Float,
|
||||
_width = BitWidthUtil.width(value),
|
||||
_value = value;
|
||||
|
||||
_StackValue.withOffset(int value, ValueType type, BitWidth width)
|
||||
: _offset = value,
|
||||
_type = type,
|
||||
_width = width;
|
||||
|
||||
BitWidth storedWidth({BitWidth width = BitWidth.width8}) {
|
||||
return ValueTypeUtils.isInline(_type) ? BitWidthUtil.max(_width, width) : _width;
|
||||
return ValueTypeUtils.isInline(_type)
|
||||
? BitWidthUtil.max(_width, width)
|
||||
: _width;
|
||||
}
|
||||
|
||||
int storedPackedType({BitWidth width = BitWidth.width8}) {
|
||||
@@ -555,16 +559,19 @@ class _StackValue {
|
||||
|
||||
BitWidth elementWidth(int size, int index) {
|
||||
if (ValueTypeUtils.isInline(_type)) return _width;
|
||||
for(var i = 0; i < 4; i++) {
|
||||
final offset = _offset!;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
final width = 1 << i;
|
||||
final offsetLoc = size + BitWidthUtil.paddingSize(size, width) + index * width;
|
||||
final offset = offsetLoc - _offset;
|
||||
final bitWidth = BitWidthUtil.uwidth(offset);
|
||||
final bitWidth = BitWidthUtil.uwidth(size +
|
||||
BitWidthUtil.paddingSize(size, width) +
|
||||
index * width -
|
||||
offset);
|
||||
if (1 << bitWidth.index == width) {
|
||||
return bitWidth;
|
||||
}
|
||||
}
|
||||
throw StateError('Element is of unknown. Size: $size at index: $index. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
|
||||
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');
|
||||
}
|
||||
|
||||
List<int> asU8List(BitWidth width) {
|
||||
@@ -572,30 +579,30 @@ class _StackValue {
|
||||
if (_type == ValueType.Float) {
|
||||
if (width == BitWidth.width32) {
|
||||
final result = ByteData(4);
|
||||
result.setFloat32(0, _value, Endian.little);
|
||||
result.setFloat32(0, _value as double, Endian.little);
|
||||
return result.buffer.asUint8List();
|
||||
} else {
|
||||
final result = ByteData(8);
|
||||
result.setFloat64(0, _value, Endian.little);
|
||||
result.setFloat64(0, _value as double, Endian.little);
|
||||
return result.buffer.asUint8List();
|
||||
}
|
||||
} else {
|
||||
switch(width) {
|
||||
switch (width) {
|
||||
case BitWidth.width8:
|
||||
final result = ByteData(1);
|
||||
result.setInt8(0, _value);
|
||||
result.setInt8(0, _value as int);
|
||||
return result.buffer.asUint8List();
|
||||
case BitWidth.width16:
|
||||
final result = ByteData(2);
|
||||
result.setInt16(0, _value, Endian.little);
|
||||
result.setInt16(0, _value as int, Endian.little);
|
||||
return result.buffer.asUint8List();
|
||||
case BitWidth.width32:
|
||||
final result = ByteData(4);
|
||||
result.setInt32(0, _value, Endian.little);
|
||||
result.setInt32(0, _value as int, Endian.little);
|
||||
return result.buffer.asUint8List();
|
||||
case BitWidth.width64:
|
||||
final result = ByteData(8);
|
||||
result.setInt64(0, _value, Endian.little);
|
||||
result.setInt64(0, _value as int, Endian.little);
|
||||
return result.buffer.asUint8List();
|
||||
}
|
||||
}
|
||||
@@ -607,11 +614,12 @@ class _StackValue {
|
||||
}
|
||||
if (_type == ValueType.Bool) {
|
||||
final result = ByteData(1);
|
||||
result.setInt8(0, _value ? 1 : 0);
|
||||
result.setInt8(0, _value as bool ? 1 : 0);
|
||||
return result.buffer.asUint8List();
|
||||
}
|
||||
|
||||
throw StateError('Unexpected type: $_type. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
|
||||
throw StateError(
|
||||
'Unexpected type: $_type. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new');
|
||||
}
|
||||
|
||||
ValueType get type {
|
||||
@@ -625,7 +633,8 @@ class _StackValue {
|
||||
bool get isOffset {
|
||||
return !ValueTypeUtils.isInline(_type);
|
||||
}
|
||||
int get offset => _offset;
|
||||
|
||||
int? get offset => _offset;
|
||||
|
||||
bool get isFloat32 {
|
||||
return _type == ValueType.Float && _width == BitWidth.width32;
|
||||
@@ -635,6 +644,7 @@ class _StackValue {
|
||||
class _StackPointer {
|
||||
int stackPosition;
|
||||
bool isVector;
|
||||
|
||||
_StackPointer(this.stackPosition, this.isVector);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,15 @@ class Reference {
|
||||
final int _offset;
|
||||
final BitWidth _parentWidth;
|
||||
final String _path;
|
||||
int _byteWidth;
|
||||
ValueType _valueType;
|
||||
int _length;
|
||||
final int _byteWidth;
|
||||
final ValueType _valueType;
|
||||
int? _length;
|
||||
|
||||
Reference._(this._buffer, this._offset, this._parentWidth, int packedType, this._path) {
|
||||
_byteWidth = 1 << (packedType & 3);
|
||||
_valueType = ValueTypeUtils.fromInt(packedType >> 2);
|
||||
}
|
||||
Reference._(
|
||||
this._buffer, this._offset, this._parentWidth, int packedType, this._path,
|
||||
[int? byteWidth, ValueType? valueType])
|
||||
: _byteWidth = byteWidth ?? 1 << (packedType & 3),
|
||||
_valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2);
|
||||
|
||||
/// Use this method to access the root value of a FlexBuffer.
|
||||
static Reference fromBuffer(ByteBuffer buffer) {
|
||||
@@ -30,31 +31,44 @@ class Reference {
|
||||
final byteWidth = byteData.getUint8(len - 1);
|
||||
final packedType = byteData.getUint8(len - 2);
|
||||
final offset = len - byteWidth - 2;
|
||||
return Reference._(ByteData.view(buffer), offset, BitWidthUtil.fromByteWidth(byteWidth), packedType, "/");
|
||||
return Reference._(ByteData.view(buffer), offset,
|
||||
BitWidthUtil.fromByteWidth(byteWidth), packedType, "/");
|
||||
}
|
||||
|
||||
/// Returns true if the underlying value is null.
|
||||
bool get isNull => _valueType == ValueType.Null;
|
||||
|
||||
/// Returns true if the underlying value can be represented as [num].
|
||||
bool get isNum => ValueTypeUtils.isNumber(_valueType) || ValueTypeUtils.isIndirectNumber(_valueType);
|
||||
bool get isNum =>
|
||||
ValueTypeUtils.isNumber(_valueType) ||
|
||||
ValueTypeUtils.isIndirectNumber(_valueType);
|
||||
|
||||
/// Returns true if the underlying value was encoded as a float (direct or indirect).
|
||||
bool get isDouble => _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat;
|
||||
bool get isDouble =>
|
||||
_valueType == ValueType.Float || _valueType == ValueType.IndirectFloat;
|
||||
|
||||
/// Returns true if the underlying value was encoded as an int or uint (direct or indirect).
|
||||
bool get isInt => isNum && !isDouble;
|
||||
|
||||
/// Returns true if the underlying value was encoded as a string or a key.
|
||||
bool get isString => _valueType == ValueType.String || _valueType == ValueType.Key;
|
||||
bool get isString =>
|
||||
_valueType == ValueType.String || _valueType == ValueType.Key;
|
||||
|
||||
/// Returns true if the underlying value was encoded as a bool.
|
||||
bool get isBool => _valueType == ValueType.Bool;
|
||||
|
||||
/// Returns true if the underlying value was encoded as a blob.
|
||||
bool get isBlob => _valueType == ValueType.Blob;
|
||||
|
||||
/// Returns true if the underlying value points to a vector.
|
||||
bool get isVector => ValueTypeUtils.isAVector(_valueType);
|
||||
|
||||
/// Returns true if the underlying value points to a map.
|
||||
bool get isMap => _valueType == ValueType.Map;
|
||||
|
||||
/// If this [isBool], returns the bool value. Otherwise, returns null.
|
||||
bool get boolValue {
|
||||
if(_valueType == ValueType.Bool) {
|
||||
bool? get boolValue {
|
||||
if (_valueType == ValueType.Bool) {
|
||||
return _readInt(_offset, _parentWidth) != 0;
|
||||
}
|
||||
return null;
|
||||
@@ -63,7 +77,7 @@ class Reference {
|
||||
/// Returns an [int], if the underlying value can be represented as an int.
|
||||
///
|
||||
/// Otherwise returns [null].
|
||||
int get intValue {
|
||||
int? get intValue {
|
||||
if (_valueType == ValueType.Int) {
|
||||
return _readInt(_offset, _parentWidth);
|
||||
}
|
||||
@@ -82,7 +96,7 @@ class Reference {
|
||||
/// Returns [double], if the underlying value [isDouble].
|
||||
///
|
||||
/// Otherwise returns [null].
|
||||
double get doubleValue {
|
||||
double? get doubleValue {
|
||||
if (_valueType == ValueType.Float) {
|
||||
return _readFloat(_offset, _parentWidth);
|
||||
}
|
||||
@@ -95,12 +109,12 @@ class Reference {
|
||||
/// Returns [num], if the underlying value is numeric, be it int uint, or float (direct or indirect).
|
||||
///
|
||||
/// Otherwise returns [null].
|
||||
num get numValue => doubleValue ?? intValue;
|
||||
num? get numValue => doubleValue ?? intValue;
|
||||
|
||||
/// Returns [String] value or null otherwise.
|
||||
///
|
||||
/// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding.
|
||||
String get stringValue {
|
||||
///
|
||||
/// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding.
|
||||
String? get stringValue {
|
||||
if (_valueType == ValueType.String || _valueType == ValueType.Key) {
|
||||
return utf8.decode(_buffer.buffer.asUint8List(_indirect, length));
|
||||
}
|
||||
@@ -108,7 +122,7 @@ class Reference {
|
||||
}
|
||||
|
||||
/// Returns [Uint8List] value or null otherwise.
|
||||
Uint8List get blobValue {
|
||||
Uint8List? get blobValue {
|
||||
if (_valueType == ValueType.Blob) {
|
||||
return _buffer.buffer.asUint8List(_indirect, length);
|
||||
}
|
||||
@@ -122,22 +136,31 @@ class Reference {
|
||||
Reference operator [](Object key) {
|
||||
if (key is int && ValueTypeUtils.isAVector(_valueType)) {
|
||||
final index = key;
|
||||
if(index >= length || index < 0) {
|
||||
throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType length: $length');
|
||||
if (index >= length || index < 0) {
|
||||
throw ArgumentError(
|
||||
'Key: [$key] is not applicable on: $_path of: $_valueType length: $length');
|
||||
}
|
||||
final elementOffset = _indirect + index * _byteWidth;
|
||||
final reference = Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), 0, "$_path[$index]");
|
||||
reference._byteWidth = 1;
|
||||
int packedType = 0;
|
||||
int? byteWidth;
|
||||
ValueType? valueType;
|
||||
if (ValueTypeUtils.isTypedVector(_valueType)) {
|
||||
reference._valueType = ValueTypeUtils.typedVectorElementType(_valueType);
|
||||
return reference;
|
||||
byteWidth = 1;
|
||||
valueType = ValueTypeUtils.typedVectorElementType(_valueType);
|
||||
} else if (ValueTypeUtils.isFixedTypedVector(_valueType)) {
|
||||
byteWidth = 1;
|
||||
valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType);
|
||||
} else {
|
||||
packedType = _buffer.getUint8(_indirect + length * _byteWidth + index);
|
||||
}
|
||||
if(ValueTypeUtils.isFixedTypedVector(_valueType)) {
|
||||
reference._valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType);
|
||||
return reference;
|
||||
}
|
||||
final packedType = _buffer.getUint8(_indirect + length * _byteWidth + index);
|
||||
return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path[$index]");
|
||||
return Reference._(
|
||||
_buffer,
|
||||
elementOffset,
|
||||
BitWidthUtil.fromByteWidth(_byteWidth),
|
||||
packedType,
|
||||
"$_path[$index]",
|
||||
byteWidth,
|
||||
valueType);
|
||||
}
|
||||
if (key is String && _valueType == ValueType.Map) {
|
||||
final index = _keyIndex(key);
|
||||
@@ -145,13 +168,14 @@ class Reference {
|
||||
return _valueForIndexWithKey(index, key);
|
||||
}
|
||||
}
|
||||
throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType');
|
||||
throw ArgumentError(
|
||||
'Key: [$key] is not applicable on: $_path of: $_valueType');
|
||||
}
|
||||
|
||||
/// Get an iterable if the underlying flexBuffer value is a vector.
|
||||
/// Otherwise throws an exception.
|
||||
Iterable<Reference> get vectorIterable {
|
||||
if(isVector == false) {
|
||||
if (isVector == false) {
|
||||
throw UnsupportedError('Value is not a vector. It is: $_valueType');
|
||||
}
|
||||
return _VectorIterator(this);
|
||||
@@ -160,7 +184,7 @@ class Reference {
|
||||
/// Get an iterable for keys if the underlying flexBuffer value is a map.
|
||||
/// Otherwise throws an exception.
|
||||
Iterable<String> get mapKeyIterable {
|
||||
if(isMap == false) {
|
||||
if (isMap == false) {
|
||||
throw UnsupportedError('Value is not a map. It is: $_valueType');
|
||||
}
|
||||
return _MapKeyIterator(this);
|
||||
@@ -169,7 +193,7 @@ class Reference {
|
||||
/// Get an iterable for values if the underlying flexBuffer value is a map.
|
||||
/// Otherwise throws an exception.
|
||||
Iterable<Reference> get mapValueIterable {
|
||||
if(isMap == false) {
|
||||
if (isMap == false) {
|
||||
throw UnsupportedError('Value is not a map. It is: $_valueType');
|
||||
}
|
||||
return _MapValueIterator(this);
|
||||
@@ -181,59 +205,62 @@ class Reference {
|
||||
/// If the underlying value is a vector, or map, the length reflects number of elements / element pairs.
|
||||
/// If the values is a string or a blob, the length reflects a number of bytes the value occupies (strings are encoded in utf8 format).
|
||||
int get length {
|
||||
if (_length != null) {
|
||||
return _length;
|
||||
}
|
||||
// needs to be checked before more generic isAVector
|
||||
if(ValueTypeUtils.isFixedTypedVector(_valueType)) {
|
||||
_length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType);
|
||||
} else if(_valueType == ValueType.Blob || ValueTypeUtils.isAVector(_valueType) || _valueType == ValueType.Map){
|
||||
_length = _readUInt(_indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
} else if (_valueType == ValueType.Null) {
|
||||
_length = 0;
|
||||
} else if (_valueType == ValueType.String) {
|
||||
final indirect = _indirect;
|
||||
var size_byte_width = _byteWidth;
|
||||
var size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width));
|
||||
while (_buffer.getInt8(indirect + size) != 0) {
|
||||
size_byte_width <<= 1;
|
||||
size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width));
|
||||
if (_length == null) {
|
||||
// needs to be checked before more generic isAVector
|
||||
if (ValueTypeUtils.isFixedTypedVector(_valueType)) {
|
||||
_length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType);
|
||||
} else if (_valueType == ValueType.Blob ||
|
||||
ValueTypeUtils.isAVector(_valueType) ||
|
||||
_valueType == ValueType.Map) {
|
||||
_length = _readUInt(
|
||||
_indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
} else if (_valueType == ValueType.Null) {
|
||||
_length = 0;
|
||||
} else if (_valueType == ValueType.String) {
|
||||
final indirect = _indirect;
|
||||
var sizeByteWidth = _byteWidth;
|
||||
var size = _readUInt(indirect - sizeByteWidth,
|
||||
BitWidthUtil.fromByteWidth(sizeByteWidth));
|
||||
while (_buffer.getInt8(indirect + size) != 0) {
|
||||
sizeByteWidth <<= 1;
|
||||
size = _readUInt(indirect - sizeByteWidth,
|
||||
BitWidthUtil.fromByteWidth(sizeByteWidth));
|
||||
}
|
||||
_length = size;
|
||||
} else if (_valueType == ValueType.Key) {
|
||||
final indirect = _indirect;
|
||||
var size = 1;
|
||||
while (_buffer.getInt8(indirect + size) != 0) {
|
||||
size += 1;
|
||||
}
|
||||
_length = size;
|
||||
} else {
|
||||
_length = 1;
|
||||
}
|
||||
_length = size;
|
||||
} else if (_valueType == ValueType.Key) {
|
||||
final indirect = _indirect;
|
||||
var size = 1;
|
||||
while (_buffer.getInt8(indirect + size) != 0) {
|
||||
size += 1;
|
||||
}
|
||||
_length = size;
|
||||
} else {
|
||||
_length = 1;
|
||||
}
|
||||
return _length;
|
||||
return _length!;
|
||||
}
|
||||
|
||||
|
||||
/// Returns a minified JSON representation of the underlying FlexBuffer value.
|
||||
///
|
||||
/// This method involves materializing the entire object tree, which may be
|
||||
/// expensive. It is more efficient to work with [Reference] and access only the needed data.
|
||||
/// Blob values are represented as base64 encoded string.
|
||||
String get json {
|
||||
if(_valueType == ValueType.Bool) {
|
||||
return boolValue ? 'true' : 'false';
|
||||
if (_valueType == ValueType.Bool) {
|
||||
return boolValue! ? 'true' : 'false';
|
||||
}
|
||||
if (_valueType == ValueType.Null) {
|
||||
return 'null';
|
||||
}
|
||||
if(ValueTypeUtils.isNumber(_valueType)) {
|
||||
if (ValueTypeUtils.isNumber(_valueType)) {
|
||||
return jsonEncode(numValue);
|
||||
}
|
||||
if (_valueType == ValueType.String) {
|
||||
return jsonEncode(stringValue);
|
||||
}
|
||||
if (_valueType == ValueType.Blob) {
|
||||
return jsonEncode(base64Encode(blobValue));
|
||||
return jsonEncode(base64Encode(blobValue!));
|
||||
}
|
||||
if (ValueTypeUtils.isAVector(_valueType)) {
|
||||
final result = StringBuffer();
|
||||
@@ -261,7 +288,8 @@ class Reference {
|
||||
result.write('}');
|
||||
return result.toString();
|
||||
}
|
||||
throw UnsupportedError('Type: $_valueType is not supported for JSON conversion');
|
||||
throw UnsupportedError(
|
||||
'Type: $_valueType is not supported for JSON conversion');
|
||||
}
|
||||
|
||||
/// Computes the indirect offset of the value.
|
||||
@@ -316,16 +344,20 @@ class Reference {
|
||||
}
|
||||
|
||||
void _validateOffset(int offset, BitWidth width) {
|
||||
if (_offset < 0 || _buffer.lengthInBytes <= offset + width.index || offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) {
|
||||
if (_offset < 0 ||
|
||||
_buffer.lengthInBytes <= offset + width.index ||
|
||||
offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) {
|
||||
throw StateError('Bad offset: $offset, width: $width');
|
||||
}
|
||||
}
|
||||
|
||||
int _keyIndex(String key) {
|
||||
int? _keyIndex(String key) {
|
||||
final input = utf8.encode(key);
|
||||
final keysVectorOffset = _indirect - _byteWidth * 3;
|
||||
final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final indirectOffset = keysVectorOffset -
|
||||
_readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final byteWidth = _readUInt(
|
||||
keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
var low = 0;
|
||||
var high = length - 1;
|
||||
while (low <= high) {
|
||||
@@ -341,9 +373,10 @@ class Reference {
|
||||
return null;
|
||||
}
|
||||
|
||||
int _diffKeys(List<int> input, int index, int indirect_offset, int byteWidth) {
|
||||
final keyOffset = indirect_offset + index * byteWidth;
|
||||
final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
|
||||
int _diffKeys(List<int> input, int index, int indirectOffset, int byteWidth) {
|
||||
final keyOffset = indirectOffset + index * byteWidth;
|
||||
final keyIndirectOffset =
|
||||
keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
final dif = input[i] - _buffer.getUint8(keyIndirectOffset + i);
|
||||
if (dif != 0) {
|
||||
@@ -357,38 +390,42 @@ class Reference {
|
||||
final indirect = _indirect;
|
||||
final elementOffset = indirect + index * _byteWidth;
|
||||
final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
|
||||
return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key");
|
||||
return Reference._(_buffer, elementOffset,
|
||||
BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key");
|
||||
}
|
||||
|
||||
Reference _valueForIndex(int index) {
|
||||
final indirect = _indirect;
|
||||
final elementOffset = indirect + index * _byteWidth;
|
||||
final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
|
||||
return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]");
|
||||
return Reference._(_buffer, elementOffset,
|
||||
BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]");
|
||||
}
|
||||
|
||||
String _keyForIndex(int index) {
|
||||
final keysVectorOffset = _indirect - _byteWidth * 3;
|
||||
final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final indirectOffset = keysVectorOffset -
|
||||
_readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final byteWidth = _readUInt(
|
||||
keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
|
||||
final keyOffset = indirectOffset + index * byteWidth;
|
||||
final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
|
||||
final keyIndirectOffset =
|
||||
keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
|
||||
var length = 0;
|
||||
while (_buffer.getUint8(keyIndirectOffset + length) != 0) {
|
||||
length += 1;
|
||||
}
|
||||
return utf8.decode(_buffer.buffer.asUint8List(keyIndirectOffset, length));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class _VectorIterator with IterableMixin<Reference> implements Iterator<Reference> {
|
||||
class _VectorIterator
|
||||
with IterableMixin<Reference>
|
||||
implements Iterator<Reference> {
|
||||
final Reference _vector;
|
||||
int index;
|
||||
int index = -1;
|
||||
|
||||
_VectorIterator(this._vector) {
|
||||
index = -1;
|
||||
}
|
||||
_VectorIterator(this._vector);
|
||||
|
||||
@override
|
||||
Reference get current => _vector[index];
|
||||
@@ -405,11 +442,9 @@ class _VectorIterator with IterableMixin<Reference> implements Iterator<Referenc
|
||||
|
||||
class _MapKeyIterator with IterableMixin<String> implements Iterator<String> {
|
||||
final Reference _map;
|
||||
int index;
|
||||
int index = -1;
|
||||
|
||||
_MapKeyIterator(this._map) {
|
||||
index = -1;
|
||||
}
|
||||
_MapKeyIterator(this._map);
|
||||
|
||||
@override
|
||||
String get current => _map._keyForIndex(index);
|
||||
@@ -424,13 +459,13 @@ class _MapKeyIterator with IterableMixin<String> implements Iterator<String> {
|
||||
Iterator<String> get iterator => this;
|
||||
}
|
||||
|
||||
class _MapValueIterator with IterableMixin<Reference> implements Iterator<Reference> {
|
||||
class _MapValueIterator
|
||||
with IterableMixin<Reference>
|
||||
implements Iterator<Reference> {
|
||||
final Reference _map;
|
||||
int index;
|
||||
int index = -1;
|
||||
|
||||
_MapValueIterator(this._map) {
|
||||
index = -1;
|
||||
}
|
||||
_MapValueIterator(this._map);
|
||||
|
||||
@override
|
||||
Reference get current => _map._valueForIndex(index);
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
/// Represents the number of bits a value occupies.
|
||||
enum BitWidth {
|
||||
width8,
|
||||
width16,
|
||||
width32,
|
||||
width64
|
||||
}
|
||||
enum BitWidth { width8, width16, width32, width64 }
|
||||
|
||||
class BitWidthUtil {
|
||||
static int toByteWidth(BitWidth self) {
|
||||
return 1 << self.index;
|
||||
}
|
||||
|
||||
static BitWidth width(num value) {
|
||||
if (value.toInt() == value) {
|
||||
var v = value.toInt().abs();
|
||||
@@ -20,8 +16,11 @@ class BitWidthUtil {
|
||||
if (v >> 31 == 0) return BitWidth.width32;
|
||||
return BitWidth.width64;
|
||||
}
|
||||
return value == _toF32(value) ? BitWidth.width32 : BitWidth.width64;
|
||||
return value == _toF32(value as double)
|
||||
? BitWidth.width32
|
||||
: BitWidth.width64;
|
||||
}
|
||||
|
||||
static BitWidth uwidth(num value) {
|
||||
if (value.toInt() == value) {
|
||||
var v = value.toInt().abs();
|
||||
@@ -30,8 +29,11 @@ class BitWidthUtil {
|
||||
if (v >> 32 == 0) return BitWidth.width32;
|
||||
return BitWidth.width64;
|
||||
}
|
||||
return value == _toF32(value) ? BitWidth.width32 : BitWidth.width64;
|
||||
return value == _toF32(value as double)
|
||||
? BitWidth.width32
|
||||
: BitWidth.width64;
|
||||
}
|
||||
|
||||
static BitWidth fromByteWidth(int value) {
|
||||
if (value == 1) {
|
||||
return BitWidth.width8;
|
||||
@@ -45,11 +47,13 @@ class BitWidthUtil {
|
||||
if (value == 8) {
|
||||
return BitWidth.width64;
|
||||
}
|
||||
throw Exception('Unexpected value ${value}');
|
||||
throw Exception('Unexpected value $value');
|
||||
}
|
||||
|
||||
static int paddingSize(int bufSize, int scalarSize) {
|
||||
return (~bufSize + 1) & (scalarSize - 1);
|
||||
}
|
||||
|
||||
static double _toF32(double value) {
|
||||
var bdata = ByteData(4);
|
||||
bdata.setFloat32(0, value);
|
||||
@@ -66,15 +70,36 @@ class BitWidthUtil {
|
||||
|
||||
/// Represents all internal FlexBuffer types.
|
||||
enum ValueType {
|
||||
Null, Int, UInt, Float,
|
||||
Key, String, IndirectInt, IndirectUInt, IndirectFloat,
|
||||
Map, Vector, VectorInt, VectorUInt, VectorFloat, VectorKey,
|
||||
@Deprecated('VectorString is deprecated due to a flaw in the binary format (https://github.com/google/flatbuffers/issues/5627)')
|
||||
Null,
|
||||
Int,
|
||||
UInt,
|
||||
Float,
|
||||
Key,
|
||||
String,
|
||||
IndirectInt,
|
||||
IndirectUInt,
|
||||
IndirectFloat,
|
||||
Map,
|
||||
Vector,
|
||||
VectorInt,
|
||||
VectorUInt,
|
||||
VectorFloat,
|
||||
VectorKey,
|
||||
@Deprecated(
|
||||
'VectorString is deprecated due to a flaw in the binary format (https://github.com/google/flatbuffers/issues/5627)')
|
||||
VectorString,
|
||||
VectorInt2, VectorUInt2, VectorFloat2,
|
||||
VectorInt3, VectorUInt3, VectorFloat3,
|
||||
VectorInt4, VectorUInt4, VectorFloat4,
|
||||
Blob, Bool, VectorBool
|
||||
VectorInt2,
|
||||
VectorUInt2,
|
||||
VectorFloat2,
|
||||
VectorInt3,
|
||||
VectorUInt3,
|
||||
VectorFloat3,
|
||||
VectorInt4,
|
||||
VectorUInt4,
|
||||
VectorFloat4,
|
||||
Blob,
|
||||
Bool,
|
||||
VectorBool
|
||||
}
|
||||
|
||||
class ValueTypeUtils {
|
||||
@@ -89,71 +114,70 @@ class ValueTypeUtils {
|
||||
}
|
||||
|
||||
static bool isInline(ValueType self) {
|
||||
return self == ValueType.Bool
|
||||
|| toInt(self) <= toInt(ValueType.Float);
|
||||
return self == ValueType.Bool || toInt(self) <= toInt(ValueType.Float);
|
||||
}
|
||||
|
||||
static bool isNumber(ValueType self) {
|
||||
return toInt(self) >= toInt(ValueType.Int)
|
||||
&& toInt(self) <= toInt(ValueType.Float);
|
||||
return toInt(self) >= toInt(ValueType.Int) &&
|
||||
toInt(self) <= toInt(ValueType.Float);
|
||||
}
|
||||
|
||||
static bool isIndirectNumber(ValueType self) {
|
||||
return toInt(self) >= toInt(ValueType.IndirectInt)
|
||||
&& toInt(self) <= toInt(ValueType.IndirectFloat);
|
||||
return toInt(self) >= toInt(ValueType.IndirectInt) &&
|
||||
toInt(self) <= toInt(ValueType.IndirectFloat);
|
||||
}
|
||||
|
||||
static bool isTypedVectorElement(ValueType self) {
|
||||
return self == ValueType.Bool ||
|
||||
(
|
||||
toInt(self) >= toInt(ValueType.Int)
|
||||
&& toInt(self) <= toInt(ValueType.String)
|
||||
);
|
||||
(toInt(self) >= toInt(ValueType.Int) &&
|
||||
toInt(self) <= toInt(ValueType.String));
|
||||
}
|
||||
|
||||
static bool isTypedVector(ValueType self) {
|
||||
return self == ValueType.VectorBool ||
|
||||
(
|
||||
toInt(self) >= toInt(ValueType.VectorInt)
|
||||
&& toInt(self) <= toInt(ValueType.VectorString)
|
||||
);
|
||||
(toInt(self) >= toInt(ValueType.VectorInt) &&
|
||||
toInt(self) <= toInt(ValueType.VectorString));
|
||||
}
|
||||
|
||||
static bool isFixedTypedVector(ValueType self) {
|
||||
return (
|
||||
toInt(self) >= toInt(ValueType.VectorInt2)
|
||||
&& toInt(self) <= toInt(ValueType.VectorFloat4)
|
||||
);
|
||||
return (toInt(self) >= toInt(ValueType.VectorInt2) &&
|
||||
toInt(self) <= toInt(ValueType.VectorFloat4));
|
||||
}
|
||||
|
||||
static bool isAVector(ValueType self) {
|
||||
return (
|
||||
isTypedVector(self) || isFixedTypedVector(self) || self == ValueType.Vector
|
||||
);
|
||||
return (isTypedVector(self) ||
|
||||
isFixedTypedVector(self) ||
|
||||
self == ValueType.Vector);
|
||||
}
|
||||
|
||||
static ValueType toTypedVector(ValueType self, int length) {
|
||||
if (length == 0) {
|
||||
return ValueTypeUtils.fromInt(toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt));
|
||||
return ValueTypeUtils.fromInt(
|
||||
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt));
|
||||
}
|
||||
if (length == 2) {
|
||||
return ValueTypeUtils.fromInt(toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2));
|
||||
return ValueTypeUtils.fromInt(
|
||||
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2));
|
||||
}
|
||||
if (length == 3) {
|
||||
return ValueTypeUtils.fromInt(toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3));
|
||||
return ValueTypeUtils.fromInt(
|
||||
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3));
|
||||
}
|
||||
if (length == 4) {
|
||||
return ValueTypeUtils.fromInt(toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt4));
|
||||
return ValueTypeUtils.fromInt(
|
||||
toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt4));
|
||||
}
|
||||
throw Exception('unexpected length ' + length.toString());
|
||||
}
|
||||
|
||||
static ValueType typedVectorElementType(ValueType self) {
|
||||
return ValueTypeUtils.fromInt(toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int));
|
||||
return ValueTypeUtils.fromInt(
|
||||
toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int));
|
||||
}
|
||||
|
||||
static ValueType fixedTypedVectorElementType(ValueType self) {
|
||||
return ValueTypeUtils.fromInt((toInt(self) - toInt(ValueType.VectorInt2)) % 3 + toInt(ValueType.Int));
|
||||
return ValueTypeUtils.fromInt(
|
||||
(toInt(self) - toInt(ValueType.VectorInt2)) % 3 + toInt(ValueType.Int));
|
||||
}
|
||||
|
||||
static int fixedTypedVectorElementSize(ValueType self) {
|
||||
|
||||
@@ -21,17 +21,12 @@ set -e
|
||||
|
||||
command -v dart >/dev/null 2>&1 || { echo >&2 "Require `dart` but it's not installed. Aborting."; exit 1; }
|
||||
|
||||
cp ../samples/monster.fbs example/
|
||||
cp ../tests/monster_test.fbs test/
|
||||
cp -r ../tests/include_test/*.fbs test/
|
||||
cp -r ../tests/include_test/sub test/
|
||||
|
||||
pushd example
|
||||
../../flatc --dart ./monster.fbs
|
||||
pushd ../tests
|
||||
./DartTest.sh
|
||||
popd
|
||||
|
||||
pushd test
|
||||
../../flatc --dart ./monster_test.fbs
|
||||
pushd ../samples
|
||||
./dart_sample.sh
|
||||
popd
|
||||
|
||||
dart pub publish
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
name: flat_buffers
|
||||
version: 2.0.0
|
||||
description: >
|
||||
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
|
||||
generate Dart classes for a FlatBuffers schema, and this library to assist with
|
||||
reading and writing the binary format.
|
||||
|
||||
Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
||||
authors:
|
||||
- Dan Field <dfield@gmail.com>
|
||||
- Konstantin Scheglov
|
||||
- Paul Berry
|
||||
description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
||||
homepage: https://github.com/google/flatbuffers
|
||||
documentation: https://google.github.io/flatbuffers/index.html
|
||||
dev_dependencies:
|
||||
test: ^1.3.0
|
||||
test_reflective_loader: ^0.1.4
|
||||
path: ^1.5.1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.0.0-dev.28.0 <3.0.0'
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.17.7
|
||||
test_reflective_loader: ^0.2.0
|
||||
path: ^1.8.0
|
||||
lints: ^1.0.1
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@ import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import './monster_test_my_game.example_generated.dart' as example;
|
||||
import './monster_test_my_game.example2_generated.dart' as example2;
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(BuilderTest);
|
||||
defineReflectiveTests(ObjectAPITest);
|
||||
defineReflectiveTests(CheckOtherLangaugesData);
|
||||
defineReflectiveTests(GeneratorTest);
|
||||
});
|
||||
@@ -28,34 +30,35 @@ int indexToField(int index) {
|
||||
@reflectiveTest
|
||||
class CheckOtherLangaugesData {
|
||||
test_cppData() async {
|
||||
List<int> data = await new io.File(path.join(
|
||||
path.dirname(io.Platform.script.path),
|
||||
List<int> data = await io.File(path.join(
|
||||
path.context.current,
|
||||
'test',
|
||||
'monsterdata_test.mon',
|
||||
)).readAsBytes();
|
||||
example.Monster mon = new example.Monster(data);
|
||||
example.Monster mon = example.Monster(data);
|
||||
expect(mon.hp, 80);
|
||||
expect(mon.mana, 150);
|
||||
expect(mon.name, 'MyMonster');
|
||||
expect(mon.pos.x, 1.0);
|
||||
expect(mon.pos.y, 2.0);
|
||||
expect(mon.pos.z, 3.0);
|
||||
expect(mon.pos.test1, 3.0);
|
||||
expect(mon.pos.test2.value, 2.0);
|
||||
expect(mon.pos.test3.a, 5);
|
||||
expect(mon.pos.test3.b, 6);
|
||||
expect(mon.testType.value, example.AnyTypeId.Monster.value);
|
||||
expect(mon.pos!.x, 1.0);
|
||||
expect(mon.pos!.y, 2.0);
|
||||
expect(mon.pos!.z, 3.0);
|
||||
expect(mon.pos!.test1, 3.0);
|
||||
expect(mon.pos!.test2.value, 2.0);
|
||||
expect(mon.pos!.test3.a, 5);
|
||||
expect(mon.pos!.test3.b, 6);
|
||||
expect(mon.testType!.value, example.AnyTypeId.Monster.value);
|
||||
expect(mon.test is example.Monster, true);
|
||||
final monster2 = mon.test as example.Monster;
|
||||
expect(monster2.name, "Fred");
|
||||
|
||||
expect(mon.inventory.length, 5);
|
||||
expect(mon.inventory.reduce((cur, next) => cur + next), 10);
|
||||
expect(mon.test4.length, 2);
|
||||
expect(
|
||||
mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100);
|
||||
expect(mon.testarrayofstring.length, 2);
|
||||
expect(mon.testarrayofstring[0], "test1");
|
||||
expect(mon.testarrayofstring[1], "test2");
|
||||
expect(mon.inventory!.length, 5);
|
||||
expect(mon.inventory!.reduce((cur, next) => cur + next), 10);
|
||||
final test4 = mon.test4!;
|
||||
expect(test4.length, 2);
|
||||
expect(test4[0].a + test4[0].b + test4[1].a + test4[1].b, 100);
|
||||
expect(mon.testarrayofstring!.length, 2);
|
||||
expect(mon.testarrayofstring![0], "test1");
|
||||
expect(mon.testarrayofstring![1], "test2");
|
||||
|
||||
// this will fail if accessing any field fails.
|
||||
expect(
|
||||
@@ -65,7 +68,7 @@ class CheckOtherLangaugesData {
|
||||
'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], '
|
||||
'color: Color{value: 8}, testType: AnyTypeId{value: 1}, '
|
||||
'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
|
||||
'inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, '
|
||||
'inventory: null, color: Color{value: 8}, testType: null, '
|
||||
'test: null, test4: null, testarrayofstring: null, '
|
||||
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
|
||||
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
|
||||
@@ -79,14 +82,13 @@ class CheckOtherLangaugesData {
|
||||
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
|
||||
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
|
||||
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
|
||||
'anyUniqueType: AnyUniqueAliasesTypeId{value: 0}, anyUnique: null, '
|
||||
'anyAmbiguousType: AnyAmbiguousAliasesTypeId{value: 0}, '
|
||||
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
|
||||
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
|
||||
'testrequirednestedflatbuffer: null}, '
|
||||
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null}, '
|
||||
'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
|
||||
'testarrayofstring: [test1, test2], testarrayoftables: null, '
|
||||
'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
|
||||
'inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, '
|
||||
'inventory: null, color: Color{value: 8}, testType: null, '
|
||||
'test: null, test4: null, testarrayofstring: null, '
|
||||
'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
|
||||
'testempty: null, testbool: false, testhashs32Fnv1: 0, '
|
||||
@@ -100,10 +102,9 @@ class CheckOtherLangaugesData {
|
||||
'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
|
||||
'coOwningReference: 0, vectorOfCoOwningReferences: null, '
|
||||
'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
|
||||
'anyUniqueType: AnyUniqueAliasesTypeId{value: 0}, anyUnique: null, '
|
||||
'anyAmbiguousType: AnyAmbiguousAliasesTypeId{value: 0}, '
|
||||
'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
|
||||
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
|
||||
'testrequirednestedflatbuffer: null}, '
|
||||
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null}, '
|
||||
'testnestedflatbuffer: null, testempty: null, testbool: true, '
|
||||
'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, '
|
||||
'testhashs64Fnv1: 7930699090847568257, '
|
||||
@@ -112,7 +113,9 @@ class CheckOtherLangaugesData {
|
||||
'testhashs64Fnv1a: 4898026182817603057, '
|
||||
'testhashu64Fnv1a: 4898026182817603057, '
|
||||
'testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, '
|
||||
'testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, '
|
||||
'testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: ['
|
||||
'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, '
|
||||
'Ability{id: 5, distance: 12}], '
|
||||
'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
|
||||
'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], '
|
||||
'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], '
|
||||
@@ -121,22 +124,43 @@ class CheckOtherLangaugesData {
|
||||
'vectorOfStrongReferrables: null, coOwningReference: 0, '
|
||||
'vectorOfCoOwningReferences: null, nonOwningReference: 0, '
|
||||
'vectorOfNonOwningReferences: null, '
|
||||
'anyUniqueType: AnyUniqueAliasesTypeId{value: 0}, anyUnique: null, '
|
||||
'anyAmbiguousType: AnyAmbiguousAliasesTypeId{value: 0}, '
|
||||
'anyUniqueType: null, anyUnique: null, '
|
||||
'anyAmbiguousType: null, '
|
||||
'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
|
||||
'testrequirednestedflatbuffer: null}',
|
||||
'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: '
|
||||
'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}]}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Test a custom, fixed-memory allocator (no actual allocations performed)
|
||||
class CustomAllocator extends Allocator {
|
||||
final _memory = ByteData(10 * 1024);
|
||||
int _used = 0;
|
||||
|
||||
Uint8List buffer(int size) => _memory.buffer.asUint8List(_used - size, size);
|
||||
|
||||
@override
|
||||
ByteData allocate(int size) {
|
||||
if (size > _memory.lengthInBytes) {
|
||||
throw UnsupportedError('Trying to allocate too much');
|
||||
}
|
||||
_used = size;
|
||||
return ByteData.sublistView(_memory, 0, size);
|
||||
}
|
||||
|
||||
@override
|
||||
void deallocate(ByteData _) {}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class BuilderTest {
|
||||
void test_monsterBuilder() {
|
||||
final fbBuilder = new Builder();
|
||||
void test_monsterBuilder([Builder? builder]) {
|
||||
final fbBuilder = builder ?? Builder();
|
||||
final str = fbBuilder.writeString('MyMonster');
|
||||
|
||||
fbBuilder.writeString('test1');
|
||||
fbBuilder.writeString('test2');
|
||||
fbBuilder.writeString('test2', asciiOptimization: true);
|
||||
final testArrayOfString = fbBuilder.endStructVector(2);
|
||||
|
||||
final fred = fbBuilder.writeString('Fred');
|
||||
@@ -144,12 +168,12 @@ class BuilderTest {
|
||||
final List<int> treasure = [0, 1, 2, 3, 4];
|
||||
final inventory = fbBuilder.writeListUint8(treasure);
|
||||
|
||||
final monBuilder = new example.MonsterBuilder(fbBuilder)
|
||||
final monBuilder = example.MonsterBuilder(fbBuilder)
|
||||
..begin()
|
||||
..addNameOffset(fred);
|
||||
final mon2 = monBuilder.finish();
|
||||
|
||||
final testBuilder = new example.TestBuilder(fbBuilder);
|
||||
final testBuilder = example.TestBuilder(fbBuilder);
|
||||
testBuilder.finish(10, 20);
|
||||
testBuilder.finish(30, 40);
|
||||
final test4 = fbBuilder.endStructVector(2);
|
||||
@@ -157,7 +181,7 @@ class BuilderTest {
|
||||
monBuilder
|
||||
..begin()
|
||||
..addPos(
|
||||
new example.Vec3Builder(fbBuilder).finish(
|
||||
example.Vec3Builder(fbBuilder).finish(
|
||||
1.0,
|
||||
2.0,
|
||||
3.0,
|
||||
@@ -177,50 +201,51 @@ class BuilderTest {
|
||||
fbBuilder.finish(mon);
|
||||
}
|
||||
|
||||
void test_error_addInt32_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
void test_error_addInt32_withoutStartTable([Builder? builder]) {
|
||||
builder ??= Builder();
|
||||
expect(() {
|
||||
builder.addInt32(0, 0);
|
||||
}, throwsStateError);
|
||||
builder!.addInt32(0, 0);
|
||||
}, throwsA(isA<AssertionError>()));
|
||||
}
|
||||
|
||||
void test_error_addOffset_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
Builder builder = Builder();
|
||||
expect(() {
|
||||
builder.addOffset(0, 0);
|
||||
}, throwsStateError);
|
||||
}, throwsA(isA<AssertionError>()));
|
||||
}
|
||||
|
||||
void test_error_endTable_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
Builder builder = Builder();
|
||||
expect(() {
|
||||
builder.endTable();
|
||||
}, throwsStateError);
|
||||
}, throwsA(isA<AssertionError>()));
|
||||
}
|
||||
|
||||
void test_error_startTable_duringTable() {
|
||||
Builder builder = new Builder();
|
||||
builder.startTable();
|
||||
Builder builder = Builder();
|
||||
builder.startTable(0);
|
||||
expect(() {
|
||||
builder.startTable();
|
||||
}, throwsStateError);
|
||||
builder.startTable(0);
|
||||
}, throwsA(isA<AssertionError>()));
|
||||
}
|
||||
|
||||
void test_error_writeString_duringTable() {
|
||||
Builder builder = new Builder();
|
||||
builder.startTable();
|
||||
Builder builder = Builder();
|
||||
builder.startTable(1);
|
||||
expect(() {
|
||||
builder.writeString('12345');
|
||||
}, throwsStateError);
|
||||
}, throwsA(isA<AssertionError>()));
|
||||
}
|
||||
|
||||
void test_file_identifier() {
|
||||
Uint8List byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
builder.startTable(0);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset, 'Az~ÿ');
|
||||
builder.finish(offset, 'Az~ÿ');
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// Convert byteList to a ByteData so that we can read data from it.
|
||||
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||
@@ -243,32 +268,46 @@ class BuilderTest {
|
||||
}
|
||||
|
||||
void test_low() {
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
expect((builder..putUint8(1)).lowFinish(), [1]);
|
||||
expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(3)).lowFinish(),
|
||||
[0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(4)).lowFinish(),
|
||||
[0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(5)).lowFinish(),
|
||||
[0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint32(6)).lowFinish(),
|
||||
final allocator = CustomAllocator();
|
||||
final builder = Builder(initialSize: 0, allocator: allocator);
|
||||
|
||||
builder.putUint8(1);
|
||||
expect(allocator.buffer(builder.size()), [1]);
|
||||
|
||||
builder.putUint32(2);
|
||||
expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
|
||||
builder.putUint8(3);
|
||||
expect(
|
||||
allocator.buffer(builder.size()), [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
|
||||
builder.putUint8(4);
|
||||
expect(
|
||||
allocator.buffer(builder.size()), [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
|
||||
builder.putUint8(5);
|
||||
expect(
|
||||
allocator.buffer(builder.size()), [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
|
||||
builder.putUint32(6);
|
||||
expect(allocator.buffer(builder.size()),
|
||||
[6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
}
|
||||
|
||||
void test_table_default() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
final builder = Builder(initialSize: 0, allocator: CustomAllocator());
|
||||
builder.startTable(2);
|
||||
builder.addInt32(0, 10, 10);
|
||||
builder.addInt32(1, 20, 10);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
expect(builder.size(), byteList.length);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buffer = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buffer = BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buffer.derefObject(0);
|
||||
// was not written, so uses the new default value
|
||||
expect(
|
||||
@@ -282,15 +321,16 @@ class BuilderTest {
|
||||
20);
|
||||
}
|
||||
|
||||
void test_table_format() {
|
||||
void test_table_format([Builder? builder]) {
|
||||
Uint8List byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
builder ??= Builder(initialSize: 0);
|
||||
builder.startTable(3);
|
||||
builder.addInt32(0, 10);
|
||||
builder.addInt32(1, 20);
|
||||
builder.addInt32(2, 30);
|
||||
byteList = builder.finish(builder.endTable());
|
||||
builder.finish(builder.endTable());
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// Convert byteList to a ByteData so that we can read data from it.
|
||||
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||
@@ -319,30 +359,37 @@ class BuilderTest {
|
||||
String unicodeString = 'Проба пера';
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int latinStringOffset = builder.writeString(latinString);
|
||||
int unicodeStringOffset = builder.writeString(unicodeString);
|
||||
builder.startTable();
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int? latinStringOffset =
|
||||
builder.writeString(latinString, asciiOptimization: true);
|
||||
int? unicodeStringOffset =
|
||||
builder.writeString(unicodeString, asciiOptimization: true);
|
||||
builder.startTable(2);
|
||||
builder.addOffset(0, latinStringOffset);
|
||||
builder.addOffset(1, unicodeStringOffset);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buf.derefObject(0);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)),
|
||||
expect(
|
||||
const StringReader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(0)),
|
||||
latinString);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)),
|
||||
expect(
|
||||
const StringReader(asciiOptimization: true)
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(1)),
|
||||
unicodeString);
|
||||
}
|
||||
|
||||
void test_table_types() {
|
||||
void test_table_types([Builder? builder]) {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int stringOffset = builder.writeString('12345');
|
||||
builder.startTable();
|
||||
builder ??= Builder(initialSize: 0);
|
||||
int? stringOffset = builder.writeString('12345');
|
||||
builder.startTable(7);
|
||||
builder.addBool(0, true);
|
||||
builder.addInt8(1, 10);
|
||||
builder.addInt32(2, 20);
|
||||
@@ -351,24 +398,39 @@ class BuilderTest {
|
||||
builder.addUint32(5, 0x9ABCDEF0);
|
||||
builder.addUint8(6, 0x9A);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buf.derefObject(0);
|
||||
expect(
|
||||
const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true);
|
||||
const BoolReader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(0)),
|
||||
true);
|
||||
expect(
|
||||
const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10);
|
||||
const Int8Reader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(1)),
|
||||
10);
|
||||
expect(
|
||||
const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)),
|
||||
const Int32Reader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(2)),
|
||||
20);
|
||||
expect(
|
||||
const StringReader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(3)),
|
||||
'12345');
|
||||
expect(
|
||||
const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40);
|
||||
expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)),
|
||||
const Int32Reader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(4)),
|
||||
40);
|
||||
expect(
|
||||
const Uint32Reader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(5)),
|
||||
0x9ABCDEF0);
|
||||
expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)),
|
||||
expect(
|
||||
const Uint8Reader()
|
||||
.vTableGetNullable(buf, objectOffset, indexToField(6)),
|
||||
0x9A);
|
||||
}
|
||||
|
||||
@@ -377,12 +439,13 @@ class BuilderTest {
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint32(values);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(4));
|
||||
expect(items, orderedEquals(values));
|
||||
@@ -393,16 +456,17 @@ class BuilderTest {
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
List<bool> values = new List<bool>.filled(len, false);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
List<bool> values = List<bool>.filled(len, false);
|
||||
for (int bit in trueBits) {
|
||||
values[bit] = true;
|
||||
}
|
||||
int offset = builder.writeListBool(values);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<bool> items = const BoolListReader().read(buf, 0);
|
||||
expect(items, hasLength(len));
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
@@ -421,25 +485,26 @@ class BuilderTest {
|
||||
verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
|
||||
verifyListBooleans(63, <int>[]);
|
||||
verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
|
||||
verifyListBooleans(63, new List<int>.generate(63, (i) => i));
|
||||
verifyListBooleans(63, List<int>.generate(63, (i) => i));
|
||||
verifyListBooleans(64, <int>[]);
|
||||
verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
|
||||
verifyListBooleans(64, <int>[1, 2, 62]);
|
||||
verifyListBooleans(64, <int>[0, 1, 2, 63]);
|
||||
verifyListBooleans(64, new List<int>.generate(64, (i) => i));
|
||||
verifyListBooleans(64, List<int>.generate(64, (i) => i));
|
||||
verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
|
||||
}
|
||||
|
||||
void test_writeList_ofInt32() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<int> items = const ListReader<int>(Int32Reader()).read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
|
||||
}
|
||||
@@ -449,13 +514,14 @@ class BuilderTest {
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListFloat64(values);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<double> items = const Float64ListReader().read(buf, 0);
|
||||
|
||||
expect(items, hasLength(values.length));
|
||||
@@ -469,12 +535,13 @@ class BuilderTest {
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListFloat32(values);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<double> items = const Float32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
@@ -482,14 +549,14 @@ class BuilderTest {
|
||||
}
|
||||
}
|
||||
|
||||
void test_writeList_ofObjects() {
|
||||
void test_writeList_ofObjects([Builder? builder]) {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder ??= Builder(initialSize: 0);
|
||||
// write the object #1
|
||||
int object1;
|
||||
{
|
||||
builder.startTable();
|
||||
builder.startTable(2);
|
||||
builder.addInt32(0, 10);
|
||||
builder.addInt32(1, 20);
|
||||
object1 = builder.endTable();
|
||||
@@ -497,19 +564,20 @@ class BuilderTest {
|
||||
// write the object #1
|
||||
int object2;
|
||||
{
|
||||
builder.startTable();
|
||||
builder.startTable(2);
|
||||
builder.addInt32(0, 100);
|
||||
builder.addInt32(1, 200);
|
||||
object2 = builder.endTable();
|
||||
}
|
||||
// write the list
|
||||
int offset = builder.writeList([object1, object2]);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<TestPointImpl> items =
|
||||
const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0);
|
||||
const ListReader<TestPointImpl>(TestPointReader()).read(buf, 0);
|
||||
expect(items, hasLength(2));
|
||||
expect(items[0].x, 10);
|
||||
expect(items[0].y, 20);
|
||||
@@ -520,36 +588,37 @@ class BuilderTest {
|
||||
void test_writeList_ofStrings_asRoot() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int str1 = builder.writeString('12345');
|
||||
int str2 = builder.writeString('ABC');
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int? str1 = builder.writeString('12345');
|
||||
int? str2 = builder.writeString('ABC');
|
||||
int offset = builder.writeList([str1, str2]);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<String> items =
|
||||
const ListReader<String>(const StringReader()).read(buf, 0);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<String> items = const ListReader<String>(StringReader()).read(buf, 0);
|
||||
expect(items, hasLength(2));
|
||||
expect(items, contains('12345'));
|
||||
expect(items, contains('ABC'));
|
||||
}
|
||||
|
||||
void test_writeList_ofStrings_inObject() {
|
||||
void test_writeList_ofStrings_inObject([Builder? builder]) {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder ??= Builder(initialSize: 0);
|
||||
int listOffset = builder.writeList(
|
||||
[builder.writeString('12345'), builder.writeString('ABC')]);
|
||||
builder.startTable();
|
||||
builder.startTable(1);
|
||||
builder.addOffset(0, listOffset);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0);
|
||||
List<String> items = reader.items;
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
StringListWrapperImpl reader = StringListWrapperReader().read(buf, 0);
|
||||
List<String>? items = reader.items;
|
||||
expect(items, hasLength(2));
|
||||
expect(items, contains('12345'));
|
||||
expect(items, contains('ABC'));
|
||||
@@ -558,12 +627,13 @@ class BuilderTest {
|
||||
void test_writeList_ofUint32() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(3));
|
||||
expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
|
||||
@@ -572,12 +642,13 @@ class BuilderTest {
|
||||
void test_writeList_ofUint16() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint16(<int>[1, 2, 60000]);
|
||||
byteList = builder.finish(offset);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint16ListReader().read(buf, 0);
|
||||
expect(items, hasLength(3));
|
||||
expect(items, orderedEquals(<int>[1, 2, 60000]));
|
||||
@@ -586,15 +657,188 @@ class BuilderTest {
|
||||
void test_writeList_ofUint8() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]);
|
||||
byteList = builder.finish(offset);
|
||||
Builder builder = Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A, 0xFA]);
|
||||
builder.finish(offset);
|
||||
byteList = builder.buffer;
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint8ListReader().read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A]));
|
||||
BufferContext buf = BufferContext.fromBytes(byteList);
|
||||
const buffOffset = 8; // 32-bit offset to the list, + 32-bit length
|
||||
for (final lazy in [true, false]) {
|
||||
List<int> items = Uint8ListReader(lazy: lazy).read(buf, 0);
|
||||
expect(items, hasLength(6));
|
||||
expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A, 0xFA]));
|
||||
|
||||
// overwrite the buffer to verify the laziness
|
||||
buf.buffer.setUint8(buffOffset + 1, 99);
|
||||
expect(items, orderedEquals(<int>[1, lazy ? 99 : 2, 3, 4, 0x9A, 0xFA]));
|
||||
|
||||
// restore the previous value for the next loop
|
||||
buf.buffer.setUint8(buffOffset + 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void test_reset() {
|
||||
// We'll run a selection of tests , reusing the builder between them.
|
||||
final testCases = <void Function(Builder?)>[
|
||||
test_monsterBuilder,
|
||||
test_error_addInt32_withoutStartTable,
|
||||
test_table_format,
|
||||
test_table_types,
|
||||
test_writeList_ofObjects,
|
||||
test_writeList_ofStrings_inObject
|
||||
];
|
||||
|
||||
// Execute all test cases in all permutations of their order.
|
||||
// To do that, we generate permutations of test case indexes.
|
||||
final testCasesPermutations =
|
||||
_permutationsOf(List.generate(testCases.length, (index) => index));
|
||||
expect(testCasesPermutations.length, _factorial(testCases.length));
|
||||
|
||||
for (var indexes in testCasesPermutations) {
|
||||
// print the order so failures are reproducible
|
||||
printOnFailure('Running reset() test cases in order: $indexes');
|
||||
|
||||
Builder? builder;
|
||||
for (var index in indexes) {
|
||||
if (builder == null) {
|
||||
// Initial size small enough so at least one test case increases it.
|
||||
// On the other hand, it's large enough so that some test cases don't.
|
||||
builder = Builder(initialSize: 32);
|
||||
} else {
|
||||
builder.reset();
|
||||
}
|
||||
testCases[index](builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate permutations of the given list
|
||||
List<List<T>> _permutationsOf<T>(List<T> source) {
|
||||
final result = <List<T>>[];
|
||||
|
||||
void permutate(List<T> items, int startAt) {
|
||||
for (var i = startAt; i < items.length; i++) {
|
||||
List<T> permutation = items.toList(growable: false);
|
||||
permutation[i] = items[startAt];
|
||||
permutation[startAt] = items[i];
|
||||
|
||||
// add the current list upon reaching the end
|
||||
if (startAt == items.length - 1) {
|
||||
result.add(items);
|
||||
} else {
|
||||
permutate(permutation, startAt + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
permutate(source, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// a very simple implementation of n!
|
||||
int _factorial(int n) {
|
||||
var result = 1;
|
||||
for (var i = 2; i <= n; i++) {
|
||||
result *= i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ObjectAPITest {
|
||||
void test_tableStat() {
|
||||
final object1 = example.StatT(count: 3, id: "foo", val: 4);
|
||||
expect(object1 is Packable, isTrue);
|
||||
final fbb = Builder();
|
||||
fbb.finish(object1.pack(fbb));
|
||||
final object2 = example.Stat(fbb.buffer).unpack();
|
||||
expect(object2.count, object1.count);
|
||||
expect(object2.id, object1.id);
|
||||
expect(object2.val, object1.val);
|
||||
expect(object2.toString(), object1.toString());
|
||||
}
|
||||
|
||||
void test_tableMonster() {
|
||||
final monster = example.MonsterT()
|
||||
..pos = example.Vec3T(
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
test1: 4.0,
|
||||
test2: example.Color.Red,
|
||||
test3: example.TestT(a: 1, b: 2))
|
||||
..mana = 2
|
||||
..name = 'Monstrous'
|
||||
..inventory = [24, 42]
|
||||
..color = example.Color.Green
|
||||
// TODO be smarter for unions and automatically set the `type` field?
|
||||
..testType = example.AnyTypeId.MyGame_Example2_Monster
|
||||
..test = example2.MonsterT()
|
||||
..test4 = [example.TestT(a: 3, b: 4), example.TestT(a: 5, b: 6)]
|
||||
..testarrayofstring = ["foo", "bar"]
|
||||
..testarrayoftables = [example.MonsterT(name: 'Oof')]
|
||||
..enemy = example.MonsterT(name: 'Enemy')
|
||||
..testarrayofbools = [false, true, false]
|
||||
..testf = 42.24
|
||||
..testarrayofsortedstruct = [
|
||||
example.AbilityT(id: 1, distance: 5),
|
||||
example.AbilityT(id: 3, distance: 7)
|
||||
]
|
||||
..vectorOfLongs = [5, 6, 7]
|
||||
..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2]
|
||||
..anyAmbiguousType = example.AnyAmbiguousAliasesTypeId.M2
|
||||
..anyAmbiguous = null
|
||||
..vectorOfEnums = [example.Color.Blue, example.Color.Green]
|
||||
..signedEnum = example.Race.None;
|
||||
|
||||
final fbBuilder = Builder();
|
||||
final offset = monster.pack(fbBuilder);
|
||||
expect(offset, isNonZero);
|
||||
fbBuilder.finish(offset);
|
||||
final data = fbBuilder.buffer;
|
||||
|
||||
// TODO currently broken because of struct builder issue, see #6688
|
||||
// final monster2 = example.Monster(data); // Monster (reader)
|
||||
// expect(
|
||||
// // map Monster => MonsterT, Vec3 => Vec3T, ...
|
||||
// monster2.toString().replaceAllMapped(
|
||||
// RegExp('([a-zA-z0-9]+){'), (match) => match.group(1) + 'T{'),
|
||||
// monster.toString());
|
||||
//
|
||||
// final monster3 = monster2.unpack(); // MonsterT
|
||||
// expect(monster3.toString(), monster.toString());
|
||||
}
|
||||
|
||||
void test_Lists() {
|
||||
// Ensure unpack() reads lists eagerly by reusing the same builder and
|
||||
// overwriting data. Why: because standard reader reads lists lazily...
|
||||
final fbb = Builder();
|
||||
|
||||
final object1 = example.TypeAliasesT(v8: [1, 2, 3], vf64: [5, 6]);
|
||||
fbb.finish(object1.pack(fbb));
|
||||
final object1Read = example.TypeAliases(fbb.buffer).unpack();
|
||||
|
||||
// overwrite the original buffer by writing to the same builder
|
||||
fbb.reset();
|
||||
final object2 = example.TypeAliasesT(v8: [7, 8, 9], vf64: [10, 11]);
|
||||
fbb.finish(object2.pack(fbb));
|
||||
final object2Read = example.TypeAliases(fbb.buffer).unpack();
|
||||
|
||||
// this is fine even with lazy lists:
|
||||
expect(object2.toString(), object2Read.toString());
|
||||
|
||||
// this fails with lazy lists:
|
||||
expect(object1.toString(), object1Read.toString());
|
||||
|
||||
// empty list must be serialized as such (were stored NULL before v2.0)
|
||||
fbb.reset();
|
||||
final object3 = example.TypeAliasesT(v8: [], vf64: null);
|
||||
fbb.finish(object3.pack(fbb));
|
||||
final object3Read = example.TypeAliases(fbb.buffer).unpack();
|
||||
expect(object3.toString(), object3Read.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,8 +848,8 @@ class StringListWrapperImpl {
|
||||
|
||||
StringListWrapperImpl(this.bp, this.offset);
|
||||
|
||||
List<String> get items => const ListReader<String>(const StringReader())
|
||||
.vTableGet(bp, offset, indexToField(0));
|
||||
List<String>? get items => const ListReader<String>(StringReader())
|
||||
.vTableGetNullable(bp, offset, indexToField(0));
|
||||
}
|
||||
|
||||
class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
|
||||
@@ -613,7 +857,7 @@ class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
|
||||
|
||||
@override
|
||||
StringListWrapperImpl createObject(BufferContext object, int offset) {
|
||||
return new StringListWrapperImpl(object, offset);
|
||||
return StringListWrapperImpl(object, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,7 +877,7 @@ class TestPointReader extends TableReader<TestPointImpl> {
|
||||
|
||||
@override
|
||||
TestPointImpl createObject(BufferContext object, int offset) {
|
||||
return new TestPointImpl(object, offset);
|
||||
return TestPointImpl(object, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,7 +887,9 @@ class GeneratorTest {
|
||||
expect(example.Color.values, same(example.Color.values));
|
||||
expect(example.Race.values, same(example.Race.values));
|
||||
expect(example.AnyTypeId.values, same(example.AnyTypeId.values));
|
||||
expect(example.AnyUniqueAliasesTypeId.values, same(example.AnyUniqueAliasesTypeId.values));
|
||||
expect(example.AnyAmbiguousAliasesTypeId.values, same(example.AnyAmbiguousAliasesTypeId.values));
|
||||
expect(example.AnyUniqueAliasesTypeId.values,
|
||||
same(example.AnyUniqueAliasesTypeId.values));
|
||||
expect(example.AnyAmbiguousAliasesTypeId.values,
|
||||
same(example.AnyAmbiguousAliasesTypeId.values));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,18 +58,18 @@ void main() {
|
||||
{
|
||||
var flx = Builder();
|
||||
flx.addString('hello 😱');
|
||||
expect(flx.finish(), [10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]);
|
||||
expect(flx.finish(),
|
||||
[10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]);
|
||||
}
|
||||
});
|
||||
|
||||
test('build vector', (){
|
||||
test('build vector', () {
|
||||
{
|
||||
var flx = Builder()
|
||||
..startVector()
|
||||
..addInt(1)
|
||||
..addInt(2)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [1, 2, 2, 64, 1]);
|
||||
}
|
||||
{
|
||||
@@ -77,8 +77,7 @@ void main() {
|
||||
..startVector()
|
||||
..addInt(-1)
|
||||
..addInt(256)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [255, 255, 0, 1, 4, 65, 1]);
|
||||
}
|
||||
{
|
||||
@@ -86,8 +85,7 @@ void main() {
|
||||
..startVector()
|
||||
..addInt(-45)
|
||||
..addInt(256000)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1]);
|
||||
}
|
||||
{
|
||||
@@ -95,9 +93,28 @@ void main() {
|
||||
..startVector()
|
||||
..addDouble(1.1)
|
||||
..addDouble(-256)
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [154, 153, 153, 153, 153, 153, 241, 63, 0, 0, 0, 0, 0, 0, 112, 192, 16, 75, 1]);
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
154,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
241,
|
||||
63,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
112,
|
||||
192,
|
||||
16,
|
||||
75,
|
||||
1
|
||||
]);
|
||||
}
|
||||
{
|
||||
var flx = Builder()
|
||||
@@ -105,8 +122,7 @@ void main() {
|
||||
..addInt(1)
|
||||
..addInt(2)
|
||||
..addInt(4)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [1, 2, 4, 3, 76, 1]);
|
||||
}
|
||||
{
|
||||
@@ -115,19 +131,17 @@ void main() {
|
||||
..addInt(-1)
|
||||
..addInt(256)
|
||||
..addInt(4)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [255, 255, 0, 1, 4, 0, 6, 77, 1]);
|
||||
}
|
||||
{
|
||||
var flx = Builder()
|
||||
..startVector()
|
||||
..startVector()
|
||||
..addInt(61)
|
||||
..end()
|
||||
..addInt(64)
|
||||
..startVector()
|
||||
..addInt(61)
|
||||
..end()
|
||||
;
|
||||
..addInt(64)
|
||||
..end();
|
||||
expect(flx.finish(), [1, 61, 2, 2, 64, 44, 4, 4, 40, 1]);
|
||||
}
|
||||
{
|
||||
@@ -136,9 +150,31 @@ void main() {
|
||||
..addString('foo')
|
||||
..addString('bar')
|
||||
..addString('baz')
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [3, 102, 111, 111, 0, 3, 98, 97, 114, 0, 3, 98, 97, 122, 0, 3, 15, 11, 7, 3, 60, 1]);
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
3,
|
||||
102,
|
||||
111,
|
||||
111,
|
||||
0,
|
||||
3,
|
||||
98,
|
||||
97,
|
||||
114,
|
||||
0,
|
||||
3,
|
||||
98,
|
||||
97,
|
||||
122,
|
||||
0,
|
||||
3,
|
||||
15,
|
||||
11,
|
||||
7,
|
||||
3,
|
||||
60,
|
||||
1
|
||||
]);
|
||||
}
|
||||
{
|
||||
var flx = Builder()
|
||||
@@ -149,9 +185,34 @@ void main() {
|
||||
..addString('foo')
|
||||
..addString('bar')
|
||||
..addString('baz')
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [3, 102, 111, 111, 0, 3, 98, 97, 114, 0, 3, 98, 97, 122, 0, 6, 15, 11, 7, 18, 14, 10, 6, 60, 1]);
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
3,
|
||||
102,
|
||||
111,
|
||||
111,
|
||||
0,
|
||||
3,
|
||||
98,
|
||||
97,
|
||||
114,
|
||||
0,
|
||||
3,
|
||||
98,
|
||||
97,
|
||||
122,
|
||||
0,
|
||||
6,
|
||||
15,
|
||||
11,
|
||||
7,
|
||||
18,
|
||||
14,
|
||||
10,
|
||||
6,
|
||||
60,
|
||||
1
|
||||
]);
|
||||
}
|
||||
{
|
||||
var flx = Builder()
|
||||
@@ -159,8 +220,7 @@ void main() {
|
||||
..addBool(true)
|
||||
..addBool(false)
|
||||
..addBool(true)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [3, 1, 0, 1, 3, 144, 1]);
|
||||
}
|
||||
{
|
||||
@@ -171,29 +231,83 @@ void main() {
|
||||
..addInt(-5)
|
||||
..addDouble(1.3)
|
||||
..addBool(true)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
3, 102, 111, 111, 0, 0, 0, 0,
|
||||
5, 0, 0, 0, 0, 0, 0, 0,
|
||||
15, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
251, 255, 255, 255, 255, 255, 255, 255,
|
||||
205, 204, 204, 204, 204, 204, 244, 63,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
20, 4, 4, 15, 104, 45, 43, 1]);
|
||||
3,
|
||||
102,
|
||||
111,
|
||||
111,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
251,
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
205,
|
||||
204,
|
||||
204,
|
||||
204,
|
||||
204,
|
||||
204,
|
||||
244,
|
||||
63,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
20,
|
||||
4,
|
||||
4,
|
||||
15,
|
||||
104,
|
||||
45,
|
||||
43,
|
||||
1
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test('build map', ()
|
||||
{
|
||||
test('build map', () {
|
||||
{
|
||||
var flx = Builder()
|
||||
..startMap()
|
||||
..addKey('a')
|
||||
..addInt(12)
|
||||
..end()
|
||||
;
|
||||
..end();
|
||||
expect(flx.finish(), [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]);
|
||||
}
|
||||
{
|
||||
@@ -203,105 +317,270 @@ void main() {
|
||||
..addInt(12)
|
||||
..addKey('')
|
||||
..addInt(45)
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]);
|
||||
..end();
|
||||
expect(
|
||||
flx.finish(), [97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]);
|
||||
}
|
||||
{
|
||||
var flx = Builder()
|
||||
..startVector()
|
||||
..startMap()
|
||||
..addKey('something')
|
||||
..addInt(12)
|
||||
..end()
|
||||
..startMap()
|
||||
..addKey('something')
|
||||
..addInt(45)
|
||||
..end()
|
||||
..startMap()
|
||||
..addKey('something')
|
||||
..addInt(12)
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [115, 111, 109, 101, 116, 104, 105, 110, 103, 0,
|
||||
1, 11, 1, 1, 1, 12, 4, 6, 1, 1, 45, 4, 2, 8, 4, 36, 36, 4, 40, 1]);
|
||||
..startMap()
|
||||
..addKey('something')
|
||||
..addInt(45)
|
||||
..end()
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
115,
|
||||
111,
|
||||
109,
|
||||
101,
|
||||
116,
|
||||
104,
|
||||
105,
|
||||
110,
|
||||
103,
|
||||
0,
|
||||
1,
|
||||
11,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
12,
|
||||
4,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
45,
|
||||
4,
|
||||
2,
|
||||
8,
|
||||
4,
|
||||
36,
|
||||
36,
|
||||
4,
|
||||
40,
|
||||
1
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test('build blob', ()
|
||||
{
|
||||
test('build blob', () {
|
||||
{
|
||||
var flx = Builder()
|
||||
..addBlob(Uint8List.fromList([1, 2, 3]).buffer)
|
||||
;
|
||||
var flx = Builder()..addBlob(Uint8List.fromList([1, 2, 3]).buffer);
|
||||
expect(flx.finish(), [3, 1, 2, 3, 3, 100, 1]);
|
||||
}
|
||||
});
|
||||
|
||||
test('build from object', (){
|
||||
expect(Builder.buildFromObject(Uint8List.fromList([1, 2, 3]).buffer).asUint8List(), [3, 1, 2, 3, 3, 100, 1]);
|
||||
test('build from object', () {
|
||||
expect(
|
||||
Builder.buildFromObject(Uint8List.fromList([1, 2, 3]).buffer)
|
||||
.asUint8List(),
|
||||
[3, 1, 2, 3, 3, 100, 1]);
|
||||
expect(Builder.buildFromObject(null).asUint8List(), [0, 0, 1]);
|
||||
expect(Builder.buildFromObject(true).asUint8List(), [1, 104, 1]);
|
||||
expect(Builder.buildFromObject(false).asUint8List(), [0, 104, 1]);
|
||||
expect(Builder.buildFromObject(25).asUint8List(), [25, 4, 1]);
|
||||
expect(Builder.buildFromObject(-250).asUint8List(), [6, 255, 5, 2]);
|
||||
expect(Builder.buildFromObject(-2.50).asUint8List(), [0, 0, 32, 192, 14, 4]);
|
||||
expect(Builder.buildFromObject('Maxim').asUint8List(), [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]);
|
||||
expect(Builder.buildFromObject([1, 3.3, 'max', true, null, false]).asUint8List(), [
|
||||
3, 109, 97, 120, 0, 0, 0, 0,
|
||||
6, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
102, 102, 102, 102, 102, 102, 10, 64,
|
||||
31, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 15, 20, 104, 0, 104, 54, 43, 1
|
||||
]);
|
||||
expect(Builder.buildFromObject([{'something':12}, {'something': 45}]).asUint8List(), [
|
||||
115, 111, 109, 101, 116, 104, 105, 110, 103, 0,
|
||||
1, 11, 1, 1, 1, 12, 4, 6, 1, 1, 45, 4, 2, 8, 4, 36, 36, 4, 40, 1
|
||||
]);
|
||||
expect(
|
||||
Builder.buildFromObject(-2.50).asUint8List(), [0, 0, 32, 192, 14, 4]);
|
||||
expect(Builder.buildFromObject('Maxim').asUint8List(),
|
||||
[5, 77, 97, 120, 105, 109, 0, 6, 20, 1]);
|
||||
expect(
|
||||
Builder.buildFromObject([1, 3.3, 'max', true, null, false])
|
||||
.asUint8List(),
|
||||
[
|
||||
3,
|
||||
109,
|
||||
97,
|
||||
120,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
102,
|
||||
102,
|
||||
102,
|
||||
102,
|
||||
102,
|
||||
102,
|
||||
10,
|
||||
64,
|
||||
31,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
15,
|
||||
20,
|
||||
104,
|
||||
0,
|
||||
104,
|
||||
54,
|
||||
43,
|
||||
1
|
||||
]);
|
||||
expect(
|
||||
Builder.buildFromObject([
|
||||
{'something': 12},
|
||||
{'something': 45}
|
||||
]).asUint8List(),
|
||||
[
|
||||
115,
|
||||
111,
|
||||
109,
|
||||
101,
|
||||
116,
|
||||
104,
|
||||
105,
|
||||
110,
|
||||
103,
|
||||
0,
|
||||
1,
|
||||
11,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
12,
|
||||
4,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
45,
|
||||
4,
|
||||
2,
|
||||
8,
|
||||
4,
|
||||
36,
|
||||
36,
|
||||
4,
|
||||
40,
|
||||
1
|
||||
]);
|
||||
});
|
||||
|
||||
test('add double indirectly', (){
|
||||
var flx = Builder()
|
||||
..addDoubleIndirectly(0.1)
|
||||
;
|
||||
test('add double indirectly', () {
|
||||
var flx = Builder()..addDoubleIndirectly(0.1);
|
||||
expect(flx.finish(), [154, 153, 153, 153, 153, 153, 185, 63, 8, 35, 1]);
|
||||
});
|
||||
|
||||
test('add double indirectly to vector with cache', (){
|
||||
test('add double indirectly to vector with cache', () {
|
||||
var flx = Builder()
|
||||
..startVector()
|
||||
..addDoubleIndirectly(0.1, cache: true)
|
||||
..addDoubleIndirectly(0.1, cache: true)
|
||||
..addDoubleIndirectly(0.1, cache: true)
|
||||
..addDoubleIndirectly(0.1, cache: true)
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [154, 153, 153, 153, 153, 153, 185, 63,
|
||||
4, 9, 10, 11, 12, 35, 35, 35, 35, 8, 40, 1]);
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
154,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
153,
|
||||
185,
|
||||
63,
|
||||
4,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
8,
|
||||
40,
|
||||
1
|
||||
]);
|
||||
});
|
||||
|
||||
test('add int indirectly', (){
|
||||
var flx = Builder()
|
||||
..addIntIndirectly(2345234523452345)
|
||||
;
|
||||
test('add int indirectly', () {
|
||||
var flx = Builder()..addIntIndirectly(2345234523452345);
|
||||
expect(flx.finish(), [185, 115, 175, 118, 250, 84, 8, 0, 8, 27, 1]);
|
||||
});
|
||||
|
||||
test('add int indirectly to vector with cache', (){
|
||||
test('add int indirectly to vector with cache', () {
|
||||
var flx = Builder()
|
||||
..startVector()
|
||||
..addIntIndirectly(2345234523452345, cache: true)
|
||||
..addIntIndirectly(2345234523452345, cache: true)
|
||||
..addIntIndirectly(2345234523452345, cache: true)
|
||||
..addIntIndirectly(2345234523452345, cache: true)
|
||||
..end()
|
||||
;
|
||||
expect(flx.finish(), [185, 115, 175, 118, 250, 84, 8, 0,
|
||||
4, 9, 10, 11, 12, 27, 27, 27, 27, 8, 40, 1]);
|
||||
..end();
|
||||
expect(flx.finish(), [
|
||||
185,
|
||||
115,
|
||||
175,
|
||||
118,
|
||||
250,
|
||||
84,
|
||||
8,
|
||||
0,
|
||||
4,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
27,
|
||||
27,
|
||||
27,
|
||||
27,
|
||||
8,
|
||||
40,
|
||||
1
|
||||
]);
|
||||
});
|
||||
|
||||
test('snapshot', (){
|
||||
test('snapshot', () {
|
||||
var flx = Builder();
|
||||
flx.startVector();
|
||||
flx.addInt(12);
|
||||
@@ -312,4 +591,3 @@ void main() {
|
||||
expect(flx.snapshot().asUint8List(), [12, 24, 45, 3, 76, 1]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,69 +48,116 @@ void main() {
|
||||
expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt), isFalse);
|
||||
});
|
||||
test('to typed vector', () {
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int,0), equals(ValueType.VectorInt));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt,0), equals(ValueType.VectorUInt));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Bool,0), equals(ValueType.VectorBool));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float,0), equals(ValueType.VectorFloat));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Key,0), equals(ValueType.VectorKey));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.String,0), equals(ValueType.VectorString));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 0),
|
||||
equals(ValueType.VectorInt));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 0),
|
||||
equals(ValueType.VectorUInt));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Bool, 0),
|
||||
equals(ValueType.VectorBool));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 0),
|
||||
equals(ValueType.VectorFloat));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Key, 0),
|
||||
equals(ValueType.VectorKey));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.String, 0),
|
||||
equals(ValueType.VectorString));
|
||||
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int,2), equals(ValueType.VectorInt2));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt,2), equals(ValueType.VectorUInt2));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float,2), equals(ValueType.VectorFloat2));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 2),
|
||||
equals(ValueType.VectorInt2));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 2),
|
||||
equals(ValueType.VectorUInt2));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 2),
|
||||
equals(ValueType.VectorFloat2));
|
||||
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int,3), equals(ValueType.VectorInt3));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt,3), equals(ValueType.VectorUInt3));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float,3), equals(ValueType.VectorFloat3));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 3),
|
||||
equals(ValueType.VectorInt3));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 3),
|
||||
equals(ValueType.VectorUInt3));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 3),
|
||||
equals(ValueType.VectorFloat3));
|
||||
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int,4), equals(ValueType.VectorInt4));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt,4), equals(ValueType.VectorUInt4));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float,4), equals(ValueType.VectorFloat4));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Int, 4),
|
||||
equals(ValueType.VectorInt4));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.UInt, 4),
|
||||
equals(ValueType.VectorUInt4));
|
||||
expect(ValueTypeUtils.toTypedVector(ValueType.Float, 4),
|
||||
equals(ValueType.VectorFloat4));
|
||||
});
|
||||
test('typed vector element type', () {
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorInt), equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt), equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat), equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorString), equals(ValueType.String));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorKey), equals(ValueType.Key));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorBool), equals(ValueType.Bool));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorInt),
|
||||
equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt),
|
||||
equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat),
|
||||
equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorString),
|
||||
equals(ValueType.String));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorKey),
|
||||
equals(ValueType.Key));
|
||||
expect(ValueTypeUtils.typedVectorElementType(ValueType.VectorBool),
|
||||
equals(ValueType.Bool));
|
||||
});
|
||||
test('fixed typed vector element type', () {
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2), equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3), equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4), equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2),
|
||||
equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3),
|
||||
equals(ValueType.Int));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4),
|
||||
equals(ValueType.Int));
|
||||
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2), equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3), equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4), equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2),
|
||||
equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3),
|
||||
equals(ValueType.UInt));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4),
|
||||
equals(ValueType.UInt));
|
||||
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2), equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3), equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4), equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2),
|
||||
equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3),
|
||||
equals(ValueType.Float));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4),
|
||||
equals(ValueType.Float));
|
||||
});
|
||||
test('fixed typed vector element size', () {
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2), equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3), equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4), equals(4));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2),
|
||||
equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3),
|
||||
equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4),
|
||||
equals(4));
|
||||
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2), equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3), equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4), equals(4));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2),
|
||||
equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3),
|
||||
equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4),
|
||||
equals(4));
|
||||
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2), equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3), equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4), equals(4));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2),
|
||||
equals(2));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3),
|
||||
equals(3));
|
||||
expect(ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4),
|
||||
equals(4));
|
||||
});
|
||||
test('packed type', () {
|
||||
expect(ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8), equals(0));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16), equals(1));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32), equals(2));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64), equals(3));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8), equals(0));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16), equals(1));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32), equals(2));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64), equals(3));
|
||||
|
||||
expect(ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8), equals(4));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16), equals(5));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32), equals(6));
|
||||
expect(ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64), equals(7));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8), equals(4));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16), equals(5));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32), equals(6));
|
||||
expect(
|
||||
ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64), equals(7));
|
||||
});
|
||||
test('bit width', () {
|
||||
expect(BitWidthUtil.width(0), BitWidth.width8);
|
||||
|
||||
154
dart/test/monster_test.fbs
Normal file
154
dart/test/monster_test.fbs
Normal file
@@ -0,0 +1,154 @@
|
||||
// test schema file
|
||||
|
||||
include "include_test1.fbs";
|
||||
|
||||
namespace MyGame;
|
||||
|
||||
table InParentNamespace {}
|
||||
|
||||
namespace MyGame.Example2;
|
||||
|
||||
table Monster {} // Test having same name as below, but in different namespace.
|
||||
|
||||
namespace MyGame.Example;
|
||||
|
||||
attribute "priority";
|
||||
|
||||
/// Composite components of Monster color.
|
||||
enum Color:ubyte (bit_flags) {
|
||||
Red = 0, // color Red = (1u << 0)
|
||||
/// \brief color Green
|
||||
/// Green is bit_flag with value (1u << 1)
|
||||
Green,
|
||||
/// \brief color Blue (1u << 3)
|
||||
Blue = 3,
|
||||
}
|
||||
|
||||
enum Race:byte {
|
||||
None = -1,
|
||||
Human = 0,
|
||||
Dwarf,
|
||||
Elf,
|
||||
}
|
||||
|
||||
union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster }
|
||||
|
||||
union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster }
|
||||
union AnyAmbiguousAliases { M1: Monster, M2: Monster, M3: Monster }
|
||||
|
||||
struct Test { a:short; b:byte; }
|
||||
|
||||
table TestSimpleTableWithEnum (csharp_partial, private) {
|
||||
color: Color = Green;
|
||||
}
|
||||
|
||||
struct Vec3 (force_align: 8) {
|
||||
x:float;
|
||||
y:float;
|
||||
z:float;
|
||||
test1:double;
|
||||
test2:Color;
|
||||
test3:Test;
|
||||
}
|
||||
|
||||
struct Ability {
|
||||
id:uint(key);
|
||||
distance:uint;
|
||||
}
|
||||
|
||||
struct StructOfStructs {
|
||||
a: Ability;
|
||||
b: Test;
|
||||
c: Ability;
|
||||
}
|
||||
|
||||
table Stat {
|
||||
id:string;
|
||||
val:long;
|
||||
count:ushort (key);
|
||||
}
|
||||
|
||||
table Referrable {
|
||||
id:ulong(key, hash:"fnv1a_64");
|
||||
}
|
||||
|
||||
/// an example documentation comment: "monster object"
|
||||
table Monster {
|
||||
pos:Vec3 (id: 0);
|
||||
hp:short = 100 (id: 2);
|
||||
mana:short = 150 (id: 1);
|
||||
name:string (id: 3, key);
|
||||
color:Color = Blue (id: 6);
|
||||
inventory:[ubyte] (id: 5);
|
||||
friendly:bool = false (deprecated, priority: 1, id: 4);
|
||||
/// an example documentation comment: this will end up in the generated code
|
||||
/// multiline too
|
||||
testarrayoftables:[Monster] (id: 11);
|
||||
testarrayofstring:[string] (id: 10);
|
||||
testarrayofstring2:[string] (id: 28);
|
||||
testarrayofbools:[bool] (id: 24);
|
||||
testarrayofsortedstruct:[Ability] (id: 29);
|
||||
enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace.
|
||||
test:Any (id: 8);
|
||||
test4:[Test] (id: 9);
|
||||
test5:[Test] (id: 31);
|
||||
testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster");
|
||||
testempty:Stat (id:14);
|
||||
testbool:bool (id:15);
|
||||
testhashs32_fnv1:int (id:16, hash:"fnv1_32");
|
||||
testhashu32_fnv1:uint (id:17, hash:"fnv1_32");
|
||||
testhashs64_fnv1:long (id:18, hash:"fnv1_64");
|
||||
testhashu64_fnv1:ulong (id:19, hash:"fnv1_64");
|
||||
testhashs32_fnv1a:int (id:20, hash:"fnv1a_32");
|
||||
testhashu32_fnv1a:uint (id:21, hash:"fnv1a_32", cpp_type:"Stat");
|
||||
testhashs64_fnv1a:long (id:22, hash:"fnv1a_64");
|
||||
testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64");
|
||||
testf:float = 3.14159 (id:25);
|
||||
testf2:float = 3 (id:26);
|
||||
testf3:float (id:27);
|
||||
flex:[ubyte] (id:30, flexbuffer);
|
||||
vector_of_longs:[long] (id:32);
|
||||
vector_of_doubles:[double] (id:33);
|
||||
parent_namespace_test:InParentNamespace (id:34);
|
||||
vector_of_referrables:[Referrable](id:35);
|
||||
single_weak_reference:ulong(id:36, hash:"fnv1a_64", cpp_type:"ReferrableT");
|
||||
vector_of_weak_references:[ulong](id:37, hash:"fnv1a_64", cpp_type:"ReferrableT");
|
||||
vector_of_strong_referrables:[Referrable](id:38, cpp_ptr_type:"default_ptr_type"); //was shared_ptr
|
||||
co_owning_reference:ulong(id:39, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked"); //was shared_ptr as well
|
||||
vector_of_co_owning_references:[ulong](id:40, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"default_ptr_type", cpp_ptr_type_get:".get()"); //was shared_ptr
|
||||
non_owning_reference:ulong(id:41, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked", cpp_ptr_type_get:""); //was weak_ptr
|
||||
vector_of_non_owning_references:[ulong](id:42, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked", cpp_ptr_type_get:""); //was weak_ptr
|
||||
any_unique:AnyUniqueAliases(id:44);
|
||||
any_ambiguous:AnyAmbiguousAliases (id:46);
|
||||
vector_of_enums:[Color] (id:47);
|
||||
signed_enum:Race = None (id:48);
|
||||
testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster");
|
||||
scalar_key_sorted_tables:[Stat] (id: 50);
|
||||
}
|
||||
|
||||
table TypeAliases {
|
||||
i8:int8;
|
||||
u8:uint8;
|
||||
i16:int16;
|
||||
u16:uint16;
|
||||
i32:int32;
|
||||
u32:uint32;
|
||||
i64:int64;
|
||||
u64:uint64;
|
||||
f32:float32;
|
||||
f64:float64;
|
||||
v8:[int8];
|
||||
vf64:[float64];
|
||||
}
|
||||
|
||||
rpc_service MonsterStorage {
|
||||
Store(Monster):Stat (streaming: "none");
|
||||
Retrieve(Stat):Monster (streaming: "server", idempotent);
|
||||
GetMaxHitPoint(Monster):Stat (streaming: "client");
|
||||
GetMinMaxHitPoints(Monster):Stat (streaming: "bidi");
|
||||
}
|
||||
|
||||
root_type Monster;
|
||||
|
||||
file_identifier "MONS";
|
||||
file_extension "mon";
|
||||
@@ -1,5 +1,5 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
library my_game.example2;
|
||||
|
||||
@@ -12,11 +12,11 @@ import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||
class Monster {
|
||||
Monster._(this._bc, this._bcOffset);
|
||||
factory Monster(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||
static const fb.Reader<Monster> reader = _MonsterReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
@@ -26,6 +26,26 @@ class Monster {
|
||||
String toString() {
|
||||
return 'Monster{}';
|
||||
}
|
||||
|
||||
MonsterT unpack() => MonsterT();
|
||||
|
||||
static int pack(fb.Builder fbBuilder, MonsterT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class MonsterT implements fb.Packable {
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(0);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MonsterT{}';
|
||||
}
|
||||
}
|
||||
|
||||
class _MonsterReader extends fb.TableReader<Monster> {
|
||||
@@ -33,7 +53,7 @@ class _MonsterReader extends fb.TableReader<Monster> {
|
||||
|
||||
@override
|
||||
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||
new Monster._(bc, offset);
|
||||
Monster._(bc, offset);
|
||||
}
|
||||
|
||||
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
@@ -42,19 +62,16 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(0);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
library my_game;
|
||||
|
||||
@@ -12,11 +12,11 @@ import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
class InParentNamespace {
|
||||
InParentNamespace._(this._bc, this._bcOffset);
|
||||
factory InParentNamespace(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<InParentNamespace> reader = const _InParentNamespaceReader();
|
||||
static const fb.Reader<InParentNamespace> reader = _InParentNamespaceReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
@@ -26,6 +26,26 @@ class InParentNamespace {
|
||||
String toString() {
|
||||
return 'InParentNamespace{}';
|
||||
}
|
||||
|
||||
InParentNamespaceT unpack() => InParentNamespaceT();
|
||||
|
||||
static int pack(fb.Builder fbBuilder, InParentNamespaceT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class InParentNamespaceT implements fb.Packable {
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(0);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InParentNamespaceT{}';
|
||||
}
|
||||
}
|
||||
|
||||
class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
|
||||
@@ -33,7 +53,7 @@ class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
|
||||
|
||||
@override
|
||||
InParentNamespace createObject(fb.BufferContext bc, int offset) =>
|
||||
new InParentNamespace._(bc, offset);
|
||||
InParentNamespace._(bc, offset);
|
||||
}
|
||||
|
||||
class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
|
||||
@@ -42,19 +62,16 @@ class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(0);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
dart/test/monsterdata_test.mon
Normal file
BIN
dart/test/monsterdata_test.mon
Normal file
Binary file not shown.
@@ -7,7 +7,7 @@ The `flatcc` C schema compiler can generate code offline as well as
|
||||
online via a C library. It can also generate buffer verifiers and fast
|
||||
JSON parsers, printers.
|
||||
|
||||
Great care has been taken to ensure compatibily with the main `flatc`
|
||||
Great care has been taken to ensure compatibility with the main `flatc`
|
||||
project.
|
||||
|
||||
## General Documention
|
||||
|
||||
@@ -79,7 +79,7 @@ Additional options:
|
||||
- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
|
||||
\x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
|
||||
|
||||
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
|
||||
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
|
||||
By default, UTF-8 characters are printed as \uXXXX escapes."
|
||||
|
||||
- `--defaults-json` : Output fields whose value is equal to the default value
|
||||
@@ -216,7 +216,9 @@ Additional options:
|
||||
- `--flexbuffers` : Used with "binary" and "json" options, it generates
|
||||
data using schema-less FlexBuffers.
|
||||
|
||||
- `--no-warnings` : Inhibit all warning messages.
|
||||
- `--no-warnings` : Inhibit all warning messages.
|
||||
|
||||
- `--cs-global-alias` : Prepend `global::` to all user generated csharp classes and structs.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -56,7 +56,7 @@ For example, here is how you would read a FlatBuffer binary file in C++:
|
||||
First, include the library and generated code. Then read the file into
|
||||
a `char *` array, which you pass to `GetMonster()`.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "monster_test_generate.h"
|
||||
#include <iostream> // C++ header file for printing
|
||||
@@ -73,18 +73,18 @@ a `char *` array, which you pass to `GetMonster()`.
|
||||
infile.close();
|
||||
|
||||
auto monster = GetMonster(data);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
`monster` is of type `Monster *`, and points to somewhere *inside* your
|
||||
buffer (root object pointers are not the same as `buffer_pointer` !).
|
||||
buffer (root object pointers are not the same as `buffer_pointer` \!).
|
||||
If you look in your generated header, you'll see it has
|
||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
std::cout << "hp : " << monster->hp() << std::endl; // `80`
|
||||
std::cout << "mana : " << monster->mana() << std::endl; // default value of `150`
|
||||
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```cpp
|
||||
std::cout << "hp : " << monster->hp() << std::endl; // '80'
|
||||
std::cout << "mana : " << monster->mana() << std::endl; // default value of '150'
|
||||
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
|
||||
```
|
||||
|
||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||
|
||||
@@ -96,7 +96,7 @@ The following attributes are supported:
|
||||
Specifically, `CreateXxxDirect` functions and `Pack` functions for object
|
||||
based API (see below) will use `CreateSharedString` to create strings.
|
||||
|
||||
## Object based API. {#flatbuffers_cpp_object_based_api}
|
||||
## Object based API {#flatbuffers_cpp_object_based_api}
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
@@ -109,7 +109,7 @@ construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
// Autogenerated class from table Monster.
|
||||
MonsterT monsterobj;
|
||||
|
||||
@@ -123,7 +123,7 @@ To use:
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb;
|
||||
fbb.Finish(Monster::Pack(fbb, &monsterobj));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
The following attributes are specific to the object-based API code generation:
|
||||
|
||||
@@ -144,19 +144,19 @@ The following attributes are specific to the object-based API code generation:
|
||||
This can be used to provide allocation from a pool for example, for faster
|
||||
unpacking when using the object-based API.
|
||||
|
||||
Minimal Example:
|
||||
Minimal Example:
|
||||
|
||||
schema:
|
||||
schema:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
table mytable(native_custom_alloc:"custom_allocator") {
|
||||
...
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
with custom_allocator defined before `flatbuffers.h` is included, as:
|
||||
with `custom_allocator` defined before `flatbuffers.h` is included, as:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
template <typename T> struct custom_allocator : public std::allocator<T> {
|
||||
|
||||
typedef T *pointer;
|
||||
@@ -175,34 +175,35 @@ The following attributes are specific to the object-based API code generation:
|
||||
}
|
||||
|
||||
custom_allocator() throw() {}
|
||||
|
||||
template <class U>
|
||||
custom_allocator(const custom_allocator<U>&) throw() {}
|
||||
};
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
- `native_type("type")` (on a struct): In some cases, a more optimal C++ data
|
||||
type exists for a given struct. For example, the following schema:
|
||||
type exists for a given struct. For example, the following schema:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
struct Vec2 {
|
||||
x: float;
|
||||
y: float;
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
generates the following Object-Based API class:
|
||||
generates the following Object-Based API class:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
struct Vec2T : flatbuffers::NativeTable {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
However, it can be useful to instead use a user-defined C++ type since it
|
||||
can provide more functionality, eg.
|
||||
However, it can be useful to instead use a user-defined C++ type since it
|
||||
can provide more functionality, eg.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
struct vector2 {
|
||||
float x = 0, y = 0;
|
||||
vector2 operator+(vector2 rhs) const { ... }
|
||||
@@ -210,22 +211,22 @@ The following attributes are specific to the object-based API code generation:
|
||||
float length() const { ... }
|
||||
// etc.
|
||||
};
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
The `native_type` attribute will replace the usage of the generated class
|
||||
with the given type. So, continuing with the example, the generated
|
||||
code would use `vector2` in place of `Vec2T` for all generated code of
|
||||
the Object-Based API.
|
||||
The `native_type` attribute will replace the usage of the generated class
|
||||
with the given type. So, continuing with the example, the generated
|
||||
code would use `vector2` in place of `Vec2T` for all generated code of
|
||||
the Object-Based API.
|
||||
|
||||
However, because the `native_type` is unknown to flatbuffers, the user must
|
||||
provide the following functions to aide in the serialization process:
|
||||
However, because the `native_type` is unknown to flatbuffers, the user must
|
||||
provide the following functions to aide in the serialization process:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
namespace flatbuffers {
|
||||
Vec2 Pack(const vector2& obj);
|
||||
vector2 UnPack(const Vec2& obj);
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
- `native_type_pack_name("name")` (on a struct when `native_type` is
|
||||
specified, too): when you want to use the same `native_type` multiple times
|
||||
@@ -235,12 +236,12 @@ The following attributes are specific to the object-based API code generation:
|
||||
specify `native_type_pack_name("Vec2")` in the above example you now need to
|
||||
implement these serialization functions instead:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
namespace flatbuffers {
|
||||
Vec2 PackVec2(const vector2& obj);
|
||||
vector2 UnPackVec2(const Vec2& obj);
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
Finally, the following top-level attributes:
|
||||
|
||||
@@ -253,7 +254,7 @@ Finally, the following top-level attributes:
|
||||
- `force_align`: this attribute may not be respected in the object API,
|
||||
depending on the aligned of the allocator used with `new`.
|
||||
|
||||
# External references.
|
||||
# External references
|
||||
|
||||
An additional feature of the object API is the ability to allow you to load
|
||||
multiple independent FlatBuffers, and have them refer to eachothers objects
|
||||
@@ -272,7 +273,7 @@ same string (or hash).
|
||||
When you call `UnPack` (or `Create`), you'll need a function that maps from
|
||||
hash to the object (see `resolver_function_t` for details).
|
||||
|
||||
# Using different pointer types.
|
||||
# Using different pointer types
|
||||
|
||||
By default the object tree is built out of `std::unique_ptr`, but you can
|
||||
influence this either globally (using the `--cpp-ptr-type` argument to
|
||||
@@ -283,13 +284,13 @@ you, so you'll have to manage their lifecycles manually. To reference the
|
||||
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
||||
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
||||
|
||||
# Using different string type.
|
||||
# Using different string type
|
||||
|
||||
By default the object tree is built out of `std::string`, but you can
|
||||
influence this either globally (using the `--cpp-str-type` argument to
|
||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
||||
|
||||
The type must support T::c_str(), T::length() and T::empty() as member functions.
|
||||
The type must support `T::c_str()`, `T::length()` and `T::empty()` as member functions.
|
||||
|
||||
Further, the type must be constructible from std::string, as by default a
|
||||
std::string instance is constructed and then used to initialize the custom
|
||||
@@ -298,7 +299,7 @@ custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
|
||||
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
|
||||
so that the custom string type is constructed by passing the pointer and
|
||||
length of the FlatBuffers String. The custom string class will require a
|
||||
constructor in the following format: custom_str_class(const char *, size_t).
|
||||
constructor in the following format: `custom_str_class(const char *, size_t)`.
|
||||
Please note that the character array is not guaranteed to be NULL terminated,
|
||||
you should always use the provided size to determine end of string.
|
||||
|
||||
@@ -309,7 +310,7 @@ read and write data even if you don't know the exact format of a buffer, and
|
||||
even allows you to change sizes of strings and vectors in-place.
|
||||
|
||||
The way this works is very elegant; there is actually a FlatBuffer schema that
|
||||
describes schemas (!) which you can find in `reflection/reflection.fbs`.
|
||||
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.
|
||||
|
||||
@@ -418,9 +419,9 @@ is accessed, all reads will end up inside the buffer.
|
||||
Each root type will have a verification function generated for it,
|
||||
e.g. for `Monster`, you can call:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
bool ok = VerifyMonsterBuffer(Verifier(buf, len));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
if `ok` is true, the buffer is safe to read.
|
||||
|
||||
@@ -486,15 +487,15 @@ Load text (either a schema or json) into an in-memory buffer (there is a
|
||||
convenient `LoadFile()` utility function in `flatbuffers/util.h` if you
|
||||
wish). Construct a parser:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
flatbuffers::Parser parser;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
Now you can parse any number of text files in sequence:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
```cpp
|
||||
parser.Parse(text_file.c_str());
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
This works similarly to how the command-line compiler works: a sequence
|
||||
of files parsed by the same `Parser` object allow later files to
|
||||
@@ -526,7 +527,7 @@ Creating a FlatBuffer is not thread safe. All state related to building
|
||||
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
|
||||
outside of it is touched. To make this thread safe, either do not
|
||||
share instances of FlatBufferBuilder between threads (recommended), or
|
||||
manually wrap it in synchronisation primites. There's no automatic way to
|
||||
manually wrap it in synchronisation primitives. There's no automatic way to
|
||||
accomplish this, by design, as we feel multithreaded construction
|
||||
of a single buffer will be rare, and synchronisation overhead would be costly.
|
||||
|
||||
|
||||
@@ -105,4 +105,27 @@ Please see the C++ documentation for more on text parsing (note that this is
|
||||
not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053)
|
||||
for the latest).
|
||||
|
||||
<br>
|
||||
## Object based API
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
(requiring pre-order construction of all data, and making mutation harder).
|
||||
|
||||
For times when efficiency is less important a more convenient object based API
|
||||
can be used (through `--gen-object-api`) that is able to unpack & pack a FlatBuffer
|
||||
into objects and lists, allowing for convenient construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
||||
// Deserialize from buffer into object.
|
||||
MonsterT monster = Monster(flatbuffer).unpack();
|
||||
|
||||
// Update object directly like a Dart class instance.
|
||||
print(monster.Name);
|
||||
monster.Name = "Bob"; // Change the name.
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
final fbb = Builder();
|
||||
fbb.Finish(monster.pack(fbb));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
35
docs/source/IntermediateRepresentation.md
Normal file
35
docs/source/IntermediateRepresentation.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Flatbuffers Intermediate Representation {#intermediate_representation}
|
||||
|
||||
We use [reflection.fbs](https://github.com/google/flatbuffers/blob/master/reflection/reflection.fbs)
|
||||
as our intermediate representation. `flatc` parses `.fbs` files, checks them for
|
||||
errors and stores the resulting data in this IR, outputting `.bfbs` files.
|
||||
Since this IR is a Flatbuffer, you can load and use it at runtime for runtime
|
||||
reflection purposes.
|
||||
|
||||
There are some quirks:
|
||||
- Tables and Structs are serialized as `Object`s.
|
||||
- Unions and Enums are serialized as `Enum`s.
|
||||
- It is the responsibility of the code generator to check the `advanced_features`
|
||||
field of `Schema`. These mark the presence of new, backwards incompatible,
|
||||
schema features. Code generators must error if generating a schema with
|
||||
unrecognized advanced features.
|
||||
- Filenames are relative to a "project root" denoted by "//" in the path. This
|
||||
may be specified in flatc with `--bfbs-filenames=$PROJECT_ROOT`, or it will be
|
||||
inferred to be the directory containing the first provided schema file.
|
||||
|
||||
|
||||
## Invocation
|
||||
You can invoke it like so
|
||||
```{.sh}
|
||||
flatc -b --schema ${your_fbs_files}
|
||||
```
|
||||
This generates `.bfbs` (binary flatbuffer schema) files.
|
||||
|
||||
Some information is not included by default. See the `--bfbs-filenames` and
|
||||
`--bfbs-comments` flags. These may be necessary for code-generators, so they can
|
||||
add documentation and maybe name generated files (depending on the generator).
|
||||
|
||||
|
||||
TODO(cneo): Flags to output bfbs as flexbuffers or json.
|
||||
|
||||
TODO(cneo): Tutorial for building a flatc plugin.
|
||||
@@ -85,7 +85,7 @@ referred to by offset.
|
||||
|
||||
They start with an `soffset_t` to a vtable. This is a signed version of
|
||||
`uoffset_t`, since vtables may be stored anywhere relative to the object.
|
||||
This offset is substracted (not added) from the object start to arrive at
|
||||
This offset is subtracted (not added) from the object start to arrive at
|
||||
the vtable start. This offset is followed by all the
|
||||
fields as aligned scalars (or offsets). Unlike structs, not all fields
|
||||
need to be present. There is no set order and layout. A table may contain
|
||||
@@ -435,7 +435,7 @@ The keys vector is a typed vector of keys. Both the keys and corresponding
|
||||
values *have* to be stored in sorted order (as determined by `strcmp`), such
|
||||
that lookups can be made using binary search.
|
||||
|
||||
The reason the key vector is a seperate structure from the value vector is
|
||||
The reason the key vector is a separate structure from the value vector is
|
||||
such that it can be shared between multiple value vectors, and also to
|
||||
allow it to be treated as its own individual vector in code.
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ https://www.npmjs.com/package/flatbuffers. To use it from sources:
|
||||
1. In your project, install it as a normal dependency, using the flatbuffers
|
||||
folder as the source.
|
||||
|
||||
## Using the FlatBuffers JavaScript libary
|
||||
## Using the FlatBuffers JavaScript library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers.*
|
||||
|
||||
@@ -71,7 +71,7 @@ Using FlatBuffers in Lobster should be relatively fast, as the implementation
|
||||
makes use of native support for writing binary values, and access of vtables.
|
||||
Both generated code and the runtime library are therefore small and fast.
|
||||
|
||||
Actual speed will depend on wether you use Lobster as bytecode VM or compiled to
|
||||
Actual speed will depend on whether you use Lobster as bytecode VM or compiled to
|
||||
C++.
|
||||
|
||||
## Text Parsing
|
||||
|
||||
@@ -36,7 +36,7 @@ The test code itself is located in
|
||||
[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
|
||||
|
||||
This test file requires `flatc` to be present. To review how to build the project,
|
||||
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
||||
|
||||
To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
|
||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||
|
||||
@@ -239,9 +239,9 @@ included files (those you still generate separately).
|
||||
|
||||
### Root type
|
||||
|
||||
This declares what you consider to be the root table (or struct) of the
|
||||
serialized data. This is particularly important for parsing JSON data,
|
||||
which doesn't include object type information.
|
||||
This declares what you consider to be the root table of the serialized
|
||||
data. This is particularly important for parsing JSON data, which doesn't
|
||||
include object type information.
|
||||
|
||||
### File identification and extension
|
||||
|
||||
@@ -490,7 +490,7 @@ as much as possible such that you can use tables where you might be
|
||||
tempted to use a dictionary.
|
||||
|
||||
Similarly, strings as values should only be used when they are
|
||||
truely open-ended. If you can, always use an enum instead.
|
||||
truly open-ended. If you can, always use an enum instead.
|
||||
|
||||
FlatBuffers doesn't have inheritance, so the way to represent a set
|
||||
of related data structures is a union. Unions do have a cost however,
|
||||
@@ -592,7 +592,7 @@ we keep the sequence of ids.
|
||||
|
||||
table { b:int; }
|
||||
|
||||
NOT ok. We can only remove a field by deprecation, regardless of wether we use
|
||||
NOT ok. We can only remove a field by deprecation, regardless of whether we use
|
||||
explicit ids or not.
|
||||
|
||||
table { a:uint; b:uint; }
|
||||
@@ -637,10 +637,14 @@ optional type.
|
||||
Some `FlatBufferBuilder` implementations have an option called `force_defaults`
|
||||
that circumvents this "not writing defaults" behavior you can then use
|
||||
`IsFieldPresent` to query presence.
|
||||
|
||||
/
|
||||
Another option that works in all languages is to wrap a scalar field in a
|
||||
struct. This way it will return null if it is not present. This will be slightly
|
||||
less ergonomic but structs don't take up any more space than the scalar they
|
||||
represent.
|
||||
|
||||
[Interface Definition Language]: https://en.wikipedia.org/wiki/Interface_description_language
|
||||
|
||||
## Writing your own code generator.
|
||||
|
||||
See [our intermediate representation](@ref intermediate_representation).
|
||||
|
||||
@@ -25,7 +25,7 @@ JSON parsing | Yes | No | No | No | No | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | Yes
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
|
||||
Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | No | No | No | No
|
||||
Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | Yes | No | No | No
|
||||
Optional Scalars | Yes | Yes | Yes | No | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
|
||||
Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | ?
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
|
||||
@@ -231,7 +231,7 @@ fields, such as `mana:short = 150`. If unspecified, scalar fields (like `int`,
|
||||
`uint`, or `float`) will be given a default of `0` while strings and tables will
|
||||
be given a default of `null`. Another thing to note is the line `friendly:bool =
|
||||
false (deprecated);`. Since you cannot delete fields from a `table` (to support
|
||||
backwards compatability), you can set fields as `deprecated`, which will prevent
|
||||
backwards compatibility), you can set fields as `deprecated`, which will prevent
|
||||
the generation of accessors for this field in the generated code. Be careful
|
||||
when using `deprecated`, however, as it may break legacy code that used this
|
||||
accessor.
|
||||
@@ -1090,7 +1090,7 @@ traversal. This is generally easy to do on any tree structures.
|
||||
</div>
|
||||
<div class="language-lua">
|
||||
~~~{.py}
|
||||
-- Serialize a name for our mosnter, called 'orc'
|
||||
-- Serialize a name for our monster, called 'orc'
|
||||
local name = builder:CreateString("Orc")
|
||||
|
||||
-- Create a `vector` representing the inventory of the Orc. Each number
|
||||
@@ -1820,7 +1820,7 @@ Here is a repetition of these lines, to help highlight them more clearly:
|
||||
<div class="language-cpp">
|
||||
~~~{.cpp}
|
||||
monster_builder.add_equipped_type(Equipment_Weapon); // Union type
|
||||
monster_builder.add_equipped(axe); // Union data
|
||||
monster_builder.add_equipped(axe.Union()); // Union data
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-java">
|
||||
@@ -2970,7 +2970,7 @@ We can access the type to dynamically cast the data as needed (since the
|
||||
|
||||
<div class="language-cpp">
|
||||
~~~{.cpp}
|
||||
auto union_type = monster.equipped_type();
|
||||
auto union_type = monster->equipped_type();
|
||||
|
||||
if (union_type == Equipment_Weapon) {
|
||||
auto weapon = static_cast<const Weapon*>(monster->equipped()); // Requires `static_cast`
|
||||
|
||||
@@ -26,7 +26,7 @@ flatbuffers/blob/master/tests/TypeScriptTest.sh) shell script.
|
||||
|
||||
*Note: The TypeScript test file requires [Node.js](https://nodejs.org/en/).*
|
||||
|
||||
## Using the FlatBuffers TypeScript libary
|
||||
## Using the FlatBuffers TypeScript library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in TypeScript.*
|
||||
|
||||
@@ -20,7 +20,7 @@ and locality.
|
||||
If it would be possible to do serialization with no temporary objects,
|
||||
no additional allocation, no copying, and good locality, this could be
|
||||
of great value. The reason serialization systems usually don't manage
|
||||
this is because it goes counter to forwards/backwards compatability, and
|
||||
this is because it goes counter to forwards/backwards compatibility, and
|
||||
platform specifics like endianness and alignment.
|
||||
|
||||
FlatBuffers is what you get if you try anyway.
|
||||
|
||||
@@ -768,6 +768,7 @@ INPUT = "FlatBuffers.md" \
|
||||
"WhitePaper.md" \
|
||||
"FlexBuffers.md" \
|
||||
"Internals.md" \
|
||||
"IntermediateRepresentation.md" \
|
||||
"Grammar.md" \
|
||||
"../../CONTRIBUTING.md" \
|
||||
"Tutorial.md" \
|
||||
|
||||
@@ -66,6 +66,8 @@
|
||||
title="FlatBuffers white paper"/>
|
||||
<tab type="user" url="@ref flatbuffers_internals"
|
||||
title="FlatBuffers internals"/>
|
||||
<tab type="user" url="@ref intermediate_representation"
|
||||
title="Intermediate Representation"/>
|
||||
<tab type="user" url="@ref flatbuffers_grammar"
|
||||
title="Grammar of the schema language"/>
|
||||
<tab type="usergroup" url="" title="API Reference">
|
||||
|
||||
@@ -32,9 +32,8 @@ $bazel test src/compiler/...
|
||||
|
||||
### Linux
|
||||
|
||||
1. `ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1`
|
||||
2. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
|
||||
3. `make test ARGS=-V`
|
||||
1. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
|
||||
2. `make test ARGS=-V`
|
||||
|
||||
For Bazel users:
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
grpc_1_36_0_githash=736e3758351ced3cd842bad3ba4e2540f01bbc48
|
||||
grpc_1_39_0_githash=58602e20a3f3e48f24a4114c757099b25b947f7b
|
||||
|
||||
function build_grpc () {
|
||||
git clone https://github.com/grpc/grpc.git google/grpc
|
||||
cd google/grpc
|
||||
git checkout ${grpc_1_36_0_githash}
|
||||
git checkout ${grpc_1_39_0_githash}
|
||||
git submodule update --init
|
||||
# Apply boringssl build patch
|
||||
cd third_party/boringssl-with-bazel
|
||||
@@ -13,11 +13,8 @@ function build_grpc () {
|
||||
cd ../..
|
||||
mkdir ../grpc_build
|
||||
cd ../grpc_build
|
||||
cmake ../grpc -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=`pwd`/../grpc/install
|
||||
cmake ../grpc -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DABSL_ENABLE_INSTALL=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=`pwd`/../grpc/install
|
||||
cmake --build . --target install ${JOBS:+-j$JOBS}
|
||||
if [ ! -f ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1 ]; then
|
||||
ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1
|
||||
fi
|
||||
cd ../..
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ generator="--grpc $current_dir/greeter.fbs"
|
||||
cd go
|
||||
|
||||
cd greeter
|
||||
fbc --go ${generator}
|
||||
fbc --bfbs-filenames ../.. --go ${generator}
|
||||
|
||||
cd ${current_dir}
|
||||
|
||||
@@ -50,7 +50,7 @@ cd python
|
||||
|
||||
cd greeter
|
||||
|
||||
fbc --python ${generator}
|
||||
fbc --bfbs-filenames ../.. --python ${generator}
|
||||
|
||||
cd ${current_dir}
|
||||
|
||||
@@ -58,7 +58,7 @@ cd ${current_dir}
|
||||
cd swift
|
||||
|
||||
cd Greeter/Sources/Model
|
||||
fbc --swift ${generator}
|
||||
fbc --bfbs-filenames ../../../.. --swift --gen-json-emit ${generator}
|
||||
|
||||
cd ${current_dir}
|
||||
|
||||
@@ -66,6 +66,6 @@ cd ${current_dir}
|
||||
cd ts
|
||||
|
||||
cd greeter/src
|
||||
fbc --ts ${generator}
|
||||
fbc --bfbs-filenames ../../.. --ts ${generator}
|
||||
|
||||
cd ${current_dir}
|
||||
|
||||
@@ -7,5 +7,5 @@ replace github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0 =>
|
||||
require (
|
||||
github.com/google/flatbuffers v1.12.0
|
||||
github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0
|
||||
google.golang.org/grpc v1.35.0
|
||||
google.golang.org/grpc v1.39.0-dev
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
models "github.com/google/flatbuffers/grpc/examples/go/greeter/models"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/encoding"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -68,8 +67,8 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
grpcServer := grpc.NewServer()
|
||||
encoding.RegisterCodec(flatbuffers.FlatbuffersCodec{})
|
||||
codec := &flatbuffers.FlatbuffersCodec{}
|
||||
grpcServer := grpc.NewServer(grpc.ForceServerCodec(codec))
|
||||
models.RegisterGreeterServer(grpcServer, newServer())
|
||||
if err := grpcServer.Serve(lis); err != nil {
|
||||
fmt.Print(err)
|
||||
|
||||
@@ -31,15 +31,12 @@ class HelloReply(object):
|
||||
return self._tab.String(o + self._tab.Pos)
|
||||
return None
|
||||
|
||||
def Start(builder): builder.StartObject(1)
|
||||
def HelloReplyStart(builder):
|
||||
"""This method is deprecated. Please switch to Start."""
|
||||
return Start(builder)
|
||||
def AddMessage(builder, message): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(message), 0)
|
||||
def HelloReplyAddMessage(builder, message):
|
||||
"""This method is deprecated. Please switch to AddMessage."""
|
||||
return AddMessage(builder, message)
|
||||
def End(builder): return builder.EndObject()
|
||||
def HelloReplyEnd(builder):
|
||||
"""This method is deprecated. Please switch to End."""
|
||||
return End(builder)
|
||||
def HelloReplyStart(builder): builder.StartObject(1)
|
||||
def Start(builder):
|
||||
return HelloReplyStart(builder)
|
||||
def HelloReplyAddMessage(builder, message): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(message), 0)
|
||||
def AddMessage(builder, message):
|
||||
return HelloReplyAddMessage(builder, message)
|
||||
def HelloReplyEnd(builder): return builder.EndObject()
|
||||
def End(builder):
|
||||
return HelloReplyEnd(builder)
|
||||
@@ -31,15 +31,12 @@ class HelloRequest(object):
|
||||
return self._tab.String(o + self._tab.Pos)
|
||||
return None
|
||||
|
||||
def Start(builder): builder.StartObject(1)
|
||||
def HelloRequestStart(builder):
|
||||
"""This method is deprecated. Please switch to Start."""
|
||||
return Start(builder)
|
||||
def AddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
|
||||
def HelloRequestAddName(builder, name):
|
||||
"""This method is deprecated. Please switch to AddName."""
|
||||
return AddName(builder, name)
|
||||
def End(builder): return builder.EndObject()
|
||||
def HelloRequestEnd(builder):
|
||||
"""This method is deprecated. Please switch to End."""
|
||||
return End(builder)
|
||||
def HelloRequestStart(builder): builder.StartObject(1)
|
||||
def Start(builder):
|
||||
return HelloRequestStart(builder)
|
||||
def HelloRequestAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
|
||||
def AddName(builder, name):
|
||||
return HelloRequestAddName(builder, name)
|
||||
def HelloRequestEnd(builder): return builder.EndObject()
|
||||
def End(builder):
|
||||
return HelloRequestEnd(builder)
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import FlatBuffers
|
||||
|
||||
public struct models_HelloReply: FlatBufferObject {
|
||||
public struct models_HelloReply: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_2_0_0() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
@@ -34,9 +34,26 @@ public struct models_HelloReply: FlatBufferObject {
|
||||
models_HelloReply.add(message: message, &fbb)
|
||||
return models_HelloReply.endHelloReply(&fbb, start: __start)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.message.p, fieldName: "message", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
public struct models_HelloRequest: FlatBufferObject {
|
||||
extension models_HelloReply: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case message = "message"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(message, forKey: .message)
|
||||
}
|
||||
}
|
||||
|
||||
public struct models_HelloRequest: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_2_0_0() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
@@ -66,5 +83,22 @@ public struct models_HelloRequest: FlatBufferObject {
|
||||
models_HelloRequest.add(name: name, &fbb)
|
||||
return models_HelloRequest.endHelloRequest(&fbb, start: __start)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
extension models_HelloRequest: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case name = "name"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(name, forKey: .name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ func greet(name: String, client greeter: models_GreeterServiceClient) {
|
||||
builder.finish(offset: root)
|
||||
|
||||
// Make the RPC call to the server.
|
||||
let sayHello = greeter.SayHello(Message<models_HelloRequest>(builder: &builder))
|
||||
let sayHello = greeter
|
||||
.SayHello(Message<models_HelloRequest>(builder: &builder))
|
||||
|
||||
// wait() on the response to stop the program from exiting before the response is received.
|
||||
do {
|
||||
@@ -54,7 +55,8 @@ func greet(name: String, client greeter: models_GreeterServiceClient) {
|
||||
builder.finish(offset: manyRoot)
|
||||
|
||||
let call = greeter.SayManyHellos(Message(builder: &builder)) { message in
|
||||
print("Greeter SayManyHellos received: \(message.object.message ?? "Unknown")")
|
||||
print(
|
||||
"Greeter SayManyHellos received: \(message.object.message ?? "Unknown")")
|
||||
}
|
||||
|
||||
let status = try! call.status.recover { _ in .processingError }.wait()
|
||||
|
||||
@@ -32,7 +32,8 @@ class Greeter: models_GreeterProvider {
|
||||
|
||||
func SayHello(
|
||||
request: Message<models_HelloRequest>,
|
||||
context: StatusOnlyCallContext) -> EventLoopFuture<Message<models_HelloReply>>
|
||||
context: StatusOnlyCallContext)
|
||||
-> EventLoopFuture<Message<models_HelloReply>>
|
||||
{
|
||||
let recipient = request.object.name ?? "Stranger"
|
||||
|
||||
@@ -40,17 +41,22 @@ class Greeter: models_GreeterProvider {
|
||||
let off = builder.create(string: "Hello \(recipient)")
|
||||
let root = models_HelloReply.createHelloReply(&builder, messageOffset: off)
|
||||
builder.finish(offset: root)
|
||||
return context.eventLoop.makeSucceededFuture(Message<models_HelloReply>(builder: &builder))
|
||||
return context.eventLoop
|
||||
.makeSucceededFuture(Message<models_HelloReply>(builder: &builder))
|
||||
}
|
||||
|
||||
func SayManyHellos(
|
||||
request: Message<models_HelloRequest>,
|
||||
context: StreamingResponseCallContext<Message<models_HelloReply>>) -> EventLoopFuture<GRPCStatus>
|
||||
context: StreamingResponseCallContext<Message<models_HelloReply>>)
|
||||
-> EventLoopFuture<GRPCStatus>
|
||||
{
|
||||
for name in greetings {
|
||||
var builder = FlatBufferBuilder()
|
||||
let off = builder.create(string: "\(name) \(request.object.name ?? "Unknown")")
|
||||
let root = models_HelloReply.createHelloReply(&builder, messageOffset: off)
|
||||
let off = builder
|
||||
.create(string: "\(name) \(request.object.name ?? "Unknown")")
|
||||
let root = models_HelloReply.createHelloReply(
|
||||
&builder,
|
||||
messageOffset: off)
|
||||
builder.finish(offset: root)
|
||||
_ = context.sendResponse(Message<models_HelloReply>(builder: &builder))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"server": "node dist/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"flatbuffers": "^2.0.0",
|
||||
"grpc": "^1.24.3"
|
||||
"@grpc/grpc-js": "^1.3.2",
|
||||
"flatbuffers": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import grpc from 'grpc';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
import { HelloReply } from './models/hello-reply';
|
||||
import { HelloRequest } from './models/hello-request';
|
||||
import { GreeterClient } from './greeter_grpc';
|
||||
import { flatbuffers } from 'flatbuffers';
|
||||
|
||||
async function main(PORT: Number, name: String) {
|
||||
const _server = new GreeterClient(`localhost:${PORT}`, grpc.credentials.createInsecure());
|
||||
async function main(PORT: Number, name: string) {
|
||||
const client = new GreeterClient(`localhost:${PORT}`, grpc.credentials.createInsecure());
|
||||
const builder = new flatbuffers.Builder();
|
||||
const offset = builder.createString(name);
|
||||
const root = HelloRequest.createHelloRequest(builder, offset);
|
||||
builder.finish(root);
|
||||
const buffer = HelloRequest.getRootAsHelloRequest(new flatbuffers.ByteBuffer(builder.asUint8Array()));
|
||||
|
||||
_server.SayHello(buffer, (err, response) => {
|
||||
client.SayHello(buffer, (err, response) => {
|
||||
console.log(response.message());
|
||||
});
|
||||
|
||||
const data = _server.SayManyHellos(buffer, null);
|
||||
const data = client.SayManyHellos(buffer, null);
|
||||
|
||||
data.on('data', (data) => {
|
||||
console.log(data.message());
|
||||
@@ -25,7 +25,7 @@ async function main(PORT: Number, name: String) {
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
const PORT = Number(args[0]);
|
||||
const name = String(args[1] ?? "flatbuffers");
|
||||
const name: string = args[1] ?? "flatbuffers";
|
||||
|
||||
if (PORT) {
|
||||
main(PORT, name);
|
||||
|
||||
2
grpc/examples/ts/greeter/src/greeter.ts
Normal file
2
grpc/examples/ts/greeter/src/greeter.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { HelloReply } from './models/hello-reply';
|
||||
export { HelloRequest } from './models/hello-request';
|
||||
@@ -3,7 +3,7 @@ import * as flatbuffers from 'flatbuffers';
|
||||
import { HelloReply as models_HelloReply } from './models/hello-reply';
|
||||
import { HelloRequest as models_HelloRequest } from './models/hello-request';
|
||||
|
||||
import * as grpc from 'grpc';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
|
||||
interface IGreeterService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
|
||||
SayHello: IGreeterService_ISayHello;
|
||||
@@ -32,7 +32,7 @@ interface IGreeterService_ISayManyHellos extends grpc.MethodDefinition<models_He
|
||||
|
||||
export const GreeterService: IGreeterService;
|
||||
|
||||
export interface IGreeterServer {
|
||||
export interface IGreeterServer extends grpc.UntypedServiceImplementation {
|
||||
SayHello: grpc.handleUnaryCall<models_HelloRequest, models_HelloReply>;
|
||||
SayManyHellos: grpc.handleServerStreamingCall<models_HelloRequest, models_HelloReply>;
|
||||
}
|
||||
@@ -46,7 +46,8 @@ export interface IGreeterClient {
|
||||
}
|
||||
|
||||
export class GreeterClient extends grpc.Client implements IGreeterClient {
|
||||
constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); public SayHello(request: models_HelloRequest, callback: (error: grpc.ServiceError | null, response: models_HelloReply) => void): grpc.ClientUnaryCall;
|
||||
constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);
|
||||
public SayHello(request: models_HelloRequest, callback: (error: grpc.ServiceError | null, response: models_HelloReply) => void): grpc.ClientUnaryCall;
|
||||
public SayHello(request: models_HelloRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: models_HelloReply) => void): grpc.ClientUnaryCall;
|
||||
public SayHello(request: models_HelloRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: models_HelloReply) => void): grpc.ClientUnaryCall;
|
||||
public SayManyHellos(request: models_HelloRequest, metadata: grpc.Metadata): grpc.ClientReadableStream<models_HelloReply>;
|
||||
|
||||
@@ -3,13 +3,13 @@ import * as flatbuffers from 'flatbuffers';
|
||||
import { HelloReply as models_HelloReply } from './models/hello-reply';
|
||||
import { HelloRequest as models_HelloRequest } from './models/hello-request';
|
||||
|
||||
var grpc = require('grpc');
|
||||
var grpc = require('@grpc/grpc-js');
|
||||
|
||||
function serialize_models_HelloReply(buffer_args) {
|
||||
if (!(buffer_args instanceof models_HelloReply)) {
|
||||
throw new Error('Expected argument of type HelloReply');
|
||||
}
|
||||
return buffer_args.serialize();
|
||||
return Buffer.from(buffer_args.serialize());
|
||||
}
|
||||
|
||||
function deserialize_models_HelloReply(buffer) {
|
||||
@@ -21,7 +21,7 @@ function serialize_models_HelloRequest(buffer_args) {
|
||||
if (!(buffer_args instanceof models_HelloRequest)) {
|
||||
throw new Error('Expected argument of type HelloRequest');
|
||||
}
|
||||
return buffer_args.serialize();
|
||||
return Buffer.from(buffer_args.serialize());
|
||||
}
|
||||
|
||||
function deserialize_models_HelloRequest(buffer) {
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import grpc from 'grpc';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
import { HelloReply } from './models/hello-reply';
|
||||
import { HelloRequest } from './models/hello-request';
|
||||
import { IGreeterServer, GreeterService } from './greeter_grpc';
|
||||
import { flatbuffers } from 'flatbuffers';
|
||||
|
||||
class GreeterServer implements IGreeterServer {
|
||||
|
||||
SayHello(call: grpc.ServerUnaryCall<HelloRequest>, callback: grpc.sendUnaryData<HelloReply>): void {
|
||||
const greeter: IGreeterServer = {
|
||||
SayHello(call: grpc.ServerUnaryCall<HelloRequest, HelloReply>, callback: grpc.sendUnaryData<HelloReply>): void {
|
||||
console.log(`SayHello ${call.request.name()}`);
|
||||
const builder = new flatbuffers.Builder();
|
||||
const offset = builder.createString(`welcome ${call.request.name()}`);
|
||||
const root = HelloReply.createHelloReply(builder, offset);
|
||||
builder.finish(root);
|
||||
callback(null, HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array())));
|
||||
}
|
||||
|
||||
async SayManyHellos(call: grpc.ServerWritableStream<HelloRequest>): Promise<void> {
|
||||
},
|
||||
async SayManyHellos(call: grpc.ServerWritableStream<HelloRequest, HelloReply>): Promise<void> {
|
||||
const name = call.request.name();
|
||||
console.log(`${call.request.name()} saying hi in different langagues`);
|
||||
['Hi', 'Hallo', 'Ciao'].forEach(element => {
|
||||
@@ -32,10 +30,20 @@ class GreeterServer implements IGreeterServer {
|
||||
function serve(): void {
|
||||
const PORT = 3000;
|
||||
const server = new grpc.Server();
|
||||
server.addService<IGreeterServer>(GreeterService, new GreeterServer());
|
||||
server.addService(GreeterService, greeter);
|
||||
console.log(`Listening on ${PORT}`);
|
||||
server.bind(`localhost:${PORT}`, grpc.ServerCredentials.createInsecure());
|
||||
server.start();
|
||||
server.bindAsync(
|
||||
`localhost:${PORT}`,
|
||||
grpc.ServerCredentials.createInsecure(),
|
||||
(err: Error | null, port: number) => {
|
||||
if (err) {
|
||||
console.error(`Server error: ${err.message}`);
|
||||
} else {
|
||||
console.log(`Server bound on port: ${port}`);
|
||||
server.start();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
serve();
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.3</version>
|
||||
</parent>
|
||||
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
@@ -24,7 +24,7 @@
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<gRPC.version>2.0.0</gRPC.version>
|
||||
<gRPC.version>1.36.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.3</version>
|
||||
<name>flatbuffers-parent</name>
|
||||
<description>parent pom for flatbuffers java artifacts</description>
|
||||
<properties>
|
||||
|
||||
@@ -114,7 +114,7 @@ grpc::string GetHeaderPrologue(grpc_generator::File *file,
|
||||
vars["filename"] = file->filename();
|
||||
vars["filename_identifier"] = FilenameIdentifier(file->filename());
|
||||
vars["filename_base"] = file->filename_without_ext();
|
||||
vars["message_header_ext"] = message_header_ext();
|
||||
vars["message_header_ext"] = file->message_header_ext();
|
||||
|
||||
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
|
||||
printer->Print(vars,
|
||||
@@ -630,7 +630,7 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
||||
"class WithAsyncMethod_$Method$ : public BaseClass {\n");
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
|
||||
" void BaseClassMustBeDerivedFromService(const Service */*service*/) {}\n");
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars,
|
||||
@@ -646,8 +646,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"$Response$* response) final override {\n"
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"$Response$* /*response*/) final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
"}\n");
|
||||
@@ -667,8 +667,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReader< $Request$>* reader, "
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
||||
"$Response$* response) final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -689,8 +689,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"::grpc::ServerWriter< $Response$>* writer) final override "
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
||||
"{\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -712,8 +712,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
|
||||
"final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -747,7 +747,7 @@ void PrintHeaderServerMethodStreamedUnary(
|
||||
"public BaseClass {\n");
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" void BaseClassMustBeDerivedFromService(const Service *service) "
|
||||
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
||||
"{}\n");
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
@@ -768,8 +768,8 @@ void PrintHeaderServerMethodStreamedUnary(
|
||||
*vars,
|
||||
"// disable regular version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"$Response$* response) final override {\n"
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"$Response$* /*response*/) final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
"}\n");
|
||||
@@ -798,8 +798,8 @@ void PrintHeaderServerMethodSplitStreaming(
|
||||
"public BaseClass {\n");
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" void BaseClassMustBeDerivedFromService(const Service *service) "
|
||||
"{}\n");
|
||||
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
||||
"{ }\n");
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
@@ -820,8 +820,8 @@ void PrintHeaderServerMethodSplitStreaming(
|
||||
*vars,
|
||||
"// disable regular version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"::grpc::ServerWriter< $Response$>* writer) final override "
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
||||
"{\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -849,7 +849,7 @@ void PrintHeaderServerMethodGeneric(
|
||||
"class WithGenericMethod_$Method$ : public BaseClass {\n");
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
|
||||
" void BaseClassMustBeDerivedFromService(const Service */*service*/) {}\n");
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars,
|
||||
@@ -865,8 +865,8 @@ void PrintHeaderServerMethodGeneric(
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"$Response$* response) final override {\n"
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"$Response$* /*response*/) final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
"}\n");
|
||||
@@ -875,9 +875,9 @@ void PrintHeaderServerMethodGeneric(
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReader< $Request$>* reader, "
|
||||
"$Response$* response) final override {\n"
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
||||
"$Response$* /*response*/) final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
"}\n");
|
||||
@@ -886,8 +886,8 @@ void PrintHeaderServerMethodGeneric(
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, const $Request$* request, "
|
||||
"::grpc::ServerWriter< $Response$>* writer) final override "
|
||||
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
||||
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
||||
"{\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -897,8 +897,8 @@ void PrintHeaderServerMethodGeneric(
|
||||
*vars,
|
||||
"// disable synchronous version of this method\n"
|
||||
"::grpc::Status $Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
|
||||
"final override {\n"
|
||||
" abort();\n"
|
||||
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
||||
@@ -1155,15 +1155,13 @@ grpc::string GetSourcePrologue(grpc_generator::File *file,
|
||||
|
||||
vars["filename"] = file->filename();
|
||||
vars["filename_base"] = file->filename_without_ext();
|
||||
vars["message_header_ext"] = message_header_ext();
|
||||
vars["service_header_ext"] = service_header_ext();
|
||||
vars["service_header_ext"] = file->service_header_ext();
|
||||
|
||||
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
|
||||
printer->Print(vars,
|
||||
"// If you make any local change, they will be lost.\n");
|
||||
printer->Print(vars, "// source: $filename$\n\n");
|
||||
|
||||
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
||||
printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
|
||||
printer->Print(vars, "\n");
|
||||
}
|
||||
@@ -1353,11 +1351,8 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
|
||||
if (method->NoStreaming()) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"const $Request$* request, $Response$* response) {\n");
|
||||
printer->Print(" (void) context;\n");
|
||||
printer->Print(" (void) request;\n");
|
||||
printer->Print(" (void) response;\n");
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"const $Request$* /*request*/, $Response$* /*response*/) {\n");
|
||||
printer->Print(
|
||||
" return ::grpc::Status("
|
||||
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
||||
@@ -1365,12 +1360,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
|
||||
} else if (ClientOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReader< $Request$>* reader, "
|
||||
"$Response$* response) {\n");
|
||||
printer->Print(" (void) context;\n");
|
||||
printer->Print(" (void) reader;\n");
|
||||
printer->Print(" (void) response;\n");
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
||||
"$Response$* /*response*/) {\n");
|
||||
printer->Print(
|
||||
" return ::grpc::Status("
|
||||
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
||||
@@ -1378,12 +1370,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
|
||||
} else if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"const $Request$* request, "
|
||||
"::grpc::ServerWriter< $Response$>* writer) {\n");
|
||||
printer->Print(" (void) context;\n");
|
||||
printer->Print(" (void) request;\n");
|
||||
printer->Print(" (void) writer;\n");
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"const $Request$* /*request*/, "
|
||||
"::grpc::ServerWriter< $Response$>* /*writer*/) {\n");
|
||||
printer->Print(
|
||||
" return ::grpc::Status("
|
||||
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
||||
@@ -1391,11 +1380,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
|
||||
} else if (method->BidiStreaming()) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerContext* /*context*/, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* "
|
||||
"stream) {\n");
|
||||
printer->Print(" (void) context;\n");
|
||||
printer->Print(" (void) stream;\n");
|
||||
"/*stream*/) {\n");
|
||||
printer->Print(
|
||||
" return ::grpc::Status("
|
||||
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
||||
@@ -1421,7 +1408,7 @@ void PrintSourceService(grpc_generator::Printer *printer,
|
||||
printer->Print(*vars,
|
||||
"std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
|
||||
"const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
|
||||
"const ::grpc::StubOptions& options) {\n"
|
||||
"const ::grpc::StubOptions& /*options*/) {\n"
|
||||
" std::unique_ptr< $ns$$Service$::Stub> stub(new "
|
||||
"$ns$$Service$::Stub(channel));\n"
|
||||
" return stub;\n"
|
||||
|
||||
@@ -93,7 +93,7 @@ struct Printer {
|
||||
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
|
||||
const char *template_string) = 0;
|
||||
virtual void Print(const char *string) = 0;
|
||||
virtual void SetIndentationSize(const int size) = 0;
|
||||
virtual void SetIndentationSize(const size_t size) = 0;
|
||||
virtual void Indent() = 0;
|
||||
virtual void Outdent() = 0;
|
||||
};
|
||||
@@ -108,6 +108,8 @@ struct File : public CommentHolder {
|
||||
virtual grpc::string package() const = 0;
|
||||
virtual std::vector<grpc::string> package_parts() const = 0;
|
||||
virtual grpc::string additional_headers() const = 0;
|
||||
virtual std::string message_header_ext() const = 0;
|
||||
virtual std::string service_header_ext() const = 0;
|
||||
|
||||
virtual int service_count() const = 0;
|
||||
virtual std::unique_ptr<const Service> service(int i) const = 0;
|
||||
|
||||
@@ -46,13 +46,14 @@ grpc::string ToDasherizedCase(const grpc::string pascal_case) {
|
||||
return dasherized_case;
|
||||
}
|
||||
|
||||
grpc::string GenerateNamespace(const std::vector<std::string> namepsace,
|
||||
|
||||
grpc::string GenerateNamespace(const std::vector<std::string> ns,
|
||||
const std::string filename,
|
||||
const bool include_separator) {
|
||||
grpc::string path = "";
|
||||
if (include_separator) path += ".";
|
||||
|
||||
for (auto it = namepsace.begin(); it < namepsace.end(); it++) {
|
||||
for (auto it = ns.begin(); it < ns.end(); it++) {
|
||||
if (include_separator) path += "/";
|
||||
path += include_separator ? ToDasherizedCase(*it) : *it + "_";
|
||||
}
|
||||
@@ -105,9 +106,9 @@ void GenerateImports(const grpc_generator::Service *service,
|
||||
}
|
||||
printer->Print("\n");
|
||||
if (grpc_var_import)
|
||||
printer->Print("var grpc = require('grpc');\n");
|
||||
printer->Print("var grpc = require('@grpc/grpc-js');\n");
|
||||
else
|
||||
printer->Print("import * as grpc from 'grpc';\n");
|
||||
printer->Print("import * as grpc from '@grpc/grpc-js';\n");
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
@@ -136,7 +137,7 @@ void GenerateSerializeMethod(grpc_generator::Printer *printer,
|
||||
"throw new Error('Expected argument of type $VALUE$');\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Print(vars, "return buffer_args.serialize();\n");
|
||||
printer->Print(vars, "return Buffer.from(buffer_args.serialize());\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
@@ -288,7 +289,9 @@ void GenerateExportedInterface(
|
||||
const grpc_generator::Service *service, grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars, "export interface I$ServiceName$Server {\n");
|
||||
printer->Print(vars,
|
||||
"export interface I$ServiceName$Server extends "
|
||||
"grpc.UntypedServiceImplementation {\n");
|
||||
printer->Indent();
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
@@ -463,7 +466,7 @@ void GenerateClientClassInterface(
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
"constructor(address: string, credentials: grpc.ChannelCredentials, "
|
||||
"options?: object);");
|
||||
"options?: object);\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["MethodName"] = method->name();
|
||||
|
||||
@@ -126,16 +126,16 @@ def run():
|
||||
Monster.MonsterStartInventoryVector(b, len(test_inventory))
|
||||
for i in range(0, len(test_inventory)):
|
||||
b.PrependByte(test_inventory[i])
|
||||
inv = b.EndVector(len(test_inventory))
|
||||
inv = b.EndVector()
|
||||
|
||||
Monster.MonsterStartTest4Vector(b, 2)
|
||||
Test.CreateTest(b, 10, 20)
|
||||
Test.CreateTest(b, 30, 40)
|
||||
test4 = b.EndVector(2)
|
||||
test4 = b.EndVector()
|
||||
|
||||
Monster.MonsterStartTestarrayofstringVector(b, 1)
|
||||
b.PrependUOffsetTRelative(test1)
|
||||
test_array_of_string = b.EndVector(1)
|
||||
test_array_of_string = b.EndVector()
|
||||
|
||||
Monster.MonsterStart(b)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ void builder_move_assign_after_releaseraw_test(
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
::grpc::Slice slice;
|
||||
dst.ReleaseRaw(size, offset, slice);
|
||||
flatbuffers::FlatBufferBuilder src;
|
||||
auto root_offset2 = populate2(src);
|
||||
@@ -39,7 +39,6 @@ void builder_move_assign_after_releaseraw_test(
|
||||
TEST_EQ(dst.GetSize(), src_size);
|
||||
TEST_ASSERT(release_n_verify(dst, m2_name(), m2_color()));
|
||||
TEST_EQ(src.GetSize(), 0);
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
|
||||
template<class SrcBuilder>
|
||||
@@ -82,10 +81,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
::grpc::Slice slice;
|
||||
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +144,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice = grpc_empty_slice();
|
||||
::grpc::Slice slice;
|
||||
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
|
||||
SrcBuilder src;
|
||||
dst = std::move(src);
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.3</version>
|
||||
</parent>
|
||||
<artifactId>grpc-test</artifactId>
|
||||
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
|
||||
</description>
|
||||
<properties>
|
||||
<gRPC.version>2.0.0</gRPC.version>
|
||||
<gRPC.version>2.0.3</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
68
include/flatbuffers/allocator.h
Normal file
68
include/flatbuffers/allocator.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_ALLOCATOR_H_
|
||||
#define FLATBUFFERS_ALLOCATOR_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Allocator interface. This is flatbuffers-specific and meant only for
|
||||
// `vector_downward` usage.
|
||||
class Allocator {
|
||||
public:
|
||||
virtual ~Allocator() {}
|
||||
|
||||
// Allocate `size` bytes of memory.
|
||||
virtual uint8_t *allocate(size_t size) = 0;
|
||||
|
||||
// Deallocate `size` bytes of memory at `p` allocated by this allocator.
|
||||
virtual void deallocate(uint8_t *p, size_t size) = 0;
|
||||
|
||||
// Reallocate `new_size` bytes of memory, replacing the old region of size
|
||||
// `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
|
||||
// and is intended specifcally for `vector_downward` use.
|
||||
// `in_use_back` and `in_use_front` indicate how much of `old_size` is
|
||||
// actually in use at each end, and needs to be copied.
|
||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) {
|
||||
FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
|
||||
uint8_t *new_p = allocate(new_size);
|
||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
||||
in_use_front);
|
||||
deallocate(old_p, old_size);
|
||||
return new_p;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
|
||||
// to `new_p` of `new_size`. Only memory of size `in_use_front` and
|
||||
// `in_use_back` will be copied from the front and back of the old memory
|
||||
// allocation.
|
||||
void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) {
|
||||
memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
|
||||
in_use_back);
|
||||
memcpy(new_p, old_p, in_use_front);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_ALLOCATOR_H_
|
||||
243
include/flatbuffers/array.h
Normal file
243
include/flatbuffers/array.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_ARRAY_H_
|
||||
#define FLATBUFFERS_ARRAY_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/stl_emulation.h"
|
||||
#include "flatbuffers/vector.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// This is used as a helper type for accessing arrays.
|
||||
template<typename T, uint16_t length> class Array {
|
||||
// Array<T> can carry only POD data types (scalars or structs).
|
||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
typedef
|
||||
typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
|
||||
IndirectHelperType;
|
||||
|
||||
public:
|
||||
typedef uint16_t size_type;
|
||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
||||
typedef VectorIterator<T, return_type> const_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
||||
static FLATBUFFERS_CONSTEXPR bool is_span_observable =
|
||||
(scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) ||
|
||||
!scalar_tag::value;
|
||||
|
||||
FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
|
||||
|
||||
return_type Get(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return IndirectHelper<IndirectHelperType>::Read(Data(), i);
|
||||
}
|
||||
|
||||
return_type operator[](uoffset_t i) const { return Get(i); }
|
||||
|
||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
||||
// type. This function makes it convenient to retrieve value with enum
|
||||
// type E.
|
||||
template<typename E> E GetEnum(uoffset_t i) const {
|
||||
return static_cast<E>(Get(i));
|
||||
}
|
||||
|
||||
const_iterator begin() const { return const_iterator(Data(), 0); }
|
||||
const_iterator end() const { return const_iterator(Data(), size()); }
|
||||
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
// Get a mutable pointer to elements inside this array.
|
||||
// This method used to mutate arrays of structs followed by a @p Mutate
|
||||
// operation. For primitive types use @p Mutate directly.
|
||||
// @warning Assignments and reads to/from the dereferenced pointer are not
|
||||
// automatically converted to the correct endianness.
|
||||
typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
|
||||
GetMutablePointer(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return const_cast<T *>(&data()[i]);
|
||||
}
|
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
|
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const { return data_; }
|
||||
|
||||
uint8_t *Data() { return data_; }
|
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); }
|
||||
T *data() { return reinterpret_cast<T *>(Data()); }
|
||||
|
||||
// Copy data from a span with endian conversion.
|
||||
// If this Array and the span overlap, the behavior is undefined.
|
||||
void CopyFromSpan(flatbuffers::span<const T, length> src) {
|
||||
const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
|
||||
const auto p2 = Data();
|
||||
FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
|
||||
!(p2 >= p1 && p2 < (p1 + length)));
|
||||
(void)p1;
|
||||
(void)p2;
|
||||
CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
|
||||
}
|
||||
|
||||
protected:
|
||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
WriteScalar(data() + i, val);
|
||||
}
|
||||
|
||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) {
|
||||
*(GetMutablePointer(i)) = val;
|
||||
}
|
||||
|
||||
void CopyFromSpanImpl(flatbuffers::true_type,
|
||||
flatbuffers::span<const T, length> src) {
|
||||
// Use std::memcpy() instead of std::copy() to avoid performance degradation
|
||||
// due to aliasing if T is char or unsigned char.
|
||||
// The size is known at compile time, so memcpy would be inlined.
|
||||
std::memcpy(data(), src.data(), length * sizeof(T));
|
||||
}
|
||||
|
||||
// Copy data from flatbuffers::span with endian conversion.
|
||||
void CopyFromSpanImpl(flatbuffers::false_type,
|
||||
flatbuffers::span<const T, length> src) {
|
||||
for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
|
||||
}
|
||||
|
||||
// This class is only used to access pre-existing data. Don't ever
|
||||
// try to construct these manually.
|
||||
// 'constexpr' allows us to use 'size()' at compile time.
|
||||
// @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
|
||||
// a constructor.
|
||||
#if defined(__cpp_constexpr)
|
||||
constexpr Array();
|
||||
#else
|
||||
Array();
|
||||
#endif
|
||||
|
||||
uint8_t data_[length * sizeof(T)];
|
||||
|
||||
private:
|
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
};
|
||||
|
||||
// Specialization for Array[struct] with access using Offset<void> pointer.
|
||||
// This specialization used by idl_gen_text.cpp.
|
||||
template<typename T, uint16_t length> class Array<Offset<T>, length> {
|
||||
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
|
||||
|
||||
public:
|
||||
typedef const void *return_type;
|
||||
|
||||
const uint8_t *Data() const { return data_; }
|
||||
|
||||
// Make idl_gen_text.cpp::PrintContainer happy.
|
||||
return_type operator[](uoffset_t) const {
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// This class is only used to access pre-existing data.
|
||||
Array();
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
|
||||
FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
||||
return span<U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
|
||||
const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(
|
||||
Array<U, N>::is_span_observable,
|
||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
||||
return span<const U, N>(arr.data(), N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
}
|
||||
|
||||
template<class U, uint16_t N>
|
||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
|
||||
make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
|
||||
static_assert(Array<U, N>::is_span_observable,
|
||||
"internal error, Array<T> might hold only scalars or structs");
|
||||
return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
||||
}
|
||||
|
||||
// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
|
||||
// without endian conversion. Use with care.
|
||||
// TODO: move these Cast-methods to `internal` namespace.
|
||||
template<typename T, uint16_t length>
|
||||
Array<T, length> &CastToArray(T (&arr)[length]) {
|
||||
return *reinterpret_cast<Array<T, length> *>(arr);
|
||||
}
|
||||
|
||||
template<typename T, uint16_t length>
|
||||
const Array<T, length> &CastToArray(const T (&arr)[length]) {
|
||||
return *reinterpret_cast<const Array<T, length> *>(arr);
|
||||
}
|
||||
|
||||
template<typename E, typename T, uint16_t length>
|
||||
Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
|
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
||||
return *reinterpret_cast<Array<E, length> *>(arr);
|
||||
}
|
||||
|
||||
template<typename E, typename T, uint16_t length>
|
||||
const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {
|
||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
||||
return *reinterpret_cast<const Array<E, length> *>(arr);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_ARRAY_H_
|
||||
@@ -50,10 +50,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _STLPORT_VERSION
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/api-level.h>
|
||||
#endif
|
||||
@@ -144,7 +140,7 @@
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 2
|
||||
#define FLATBUFFERS_VERSION_MINOR 0
|
||||
#define FLATBUFFERS_VERSION_REVISION 0
|
||||
#define FLATBUFFERS_VERSION_REVISION 5
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
namespace flatbuffers {
|
||||
@@ -247,6 +243,11 @@ namespace flatbuffers {
|
||||
#endif // __has_include
|
||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
#ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
|
||||
// Allow heap allocations to be used
|
||||
#define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1
|
||||
#endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
|
||||
|
||||
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
|
||||
// Modern (C++11) strtod and strtof functions are available for use.
|
||||
// 1) nan/inf strings as argument of strtod;
|
||||
@@ -289,7 +290,7 @@ template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
||||
#if ((__cplusplus >= 201703L) \
|
||||
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
|
||||
// All attributes unknown to an implementation are ignored without causing an error.
|
||||
#define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
|
||||
#define FLATBUFFERS_ATTRIBUTE(attr) attr
|
||||
|
||||
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
|
||||
#else
|
||||
@@ -330,6 +331,9 @@ typedef uintmax_t largest_scalar_t;
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||
|
||||
/// @brief The length of a FlatBuffer file header.
|
||||
static const size_t kFileIdentifierLength = 4;
|
||||
|
||||
inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) {
|
||||
return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) &&
|
||||
(align & (align - 1)) == 0; // must be power of 2
|
||||
@@ -433,5 +437,38 @@ inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
// Generic 'operator==' with conditional specialisations.
|
||||
// T e - new value of a scalar field.
|
||||
// T def - default of scalar (is known at compile-time).
|
||||
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
|
||||
|
||||
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
|
||||
defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
|
||||
// Like `operator==(e, def)` with weak NaN if T=(float|double).
|
||||
template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
|
||||
return (e == def) || ((def != def) && (e != e));
|
||||
}
|
||||
template<> inline bool IsTheSameAs<float>(float e, float def) {
|
||||
return IsFloatTheSameAs(e, def);
|
||||
}
|
||||
template<> inline bool IsTheSameAs<double>(double e, double def) {
|
||||
return IsFloatTheSameAs(e, def);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check 'v' is out of closed range [low; high].
|
||||
// Workaround for GCC warning [-Werror=type-limits]:
|
||||
// comparison is always true due to limited range of data type.
|
||||
template<typename T>
|
||||
inline bool IsOutRange(const T &v, const T &low, const T &high) {
|
||||
return (v < low) || (high < v);
|
||||
}
|
||||
|
||||
// Check 'v' is in closed range [low; high].
|
||||
template<typename T>
|
||||
inline bool IsInRange(const T &v, const T &low, const T &high) {
|
||||
return !IsOutRange(v, low, high);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
#endif // FLATBUFFERS_BASE_H_
|
||||
|
||||
43
include/flatbuffers/bfbs_generator.h
Normal file
43
include/flatbuffers/bfbs_generator.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_BFBS_GENERATOR_H_
|
||||
#define FLATBUFFERS_BFBS_GENERATOR_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
enum GeneratorStatus {
|
||||
OK,
|
||||
FAILED,
|
||||
FAILED_VERIFICATION,
|
||||
};
|
||||
|
||||
// A Flatbuffer Code Generator that receives a binary serialized reflection.fbs
|
||||
// and generates code from it.
|
||||
class BfbsGenerator {
|
||||
public:
|
||||
virtual ~BfbsGenerator() {}
|
||||
|
||||
// Generate code from the provided `buffer` of given `length`. The buffer is
|
||||
// a serialized reflection.fbs.
|
||||
virtual GeneratorStatus Generate(const uint8_t *buffer, int64_t length) = 0;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BFBS_GENERATOR_H_
|
||||
142
include/flatbuffers/buffer.h
Normal file
142
include/flatbuffers/buffer.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_BUFFER_H_
|
||||
#define FLATBUFFERS_BUFFER_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Wrapper for uoffset_t to allow safe template specialization.
|
||||
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
|
||||
template<typename T> struct Offset {
|
||||
uoffset_t o;
|
||||
Offset() : o(0) {}
|
||||
Offset(uoffset_t _o) : o(_o) {}
|
||||
Offset<void> Union() const { return Offset<void>(o); }
|
||||
bool IsNull() const { return !o; }
|
||||
};
|
||||
|
||||
inline void EndianCheck() {
|
||||
int endiantest = 1;
|
||||
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
|
||||
FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
|
||||
FLATBUFFERS_LITTLEENDIAN);
|
||||
(void)endiantest;
|
||||
}
|
||||
|
||||
template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
|
||||
// clang-format off
|
||||
#ifdef _MSC_VER
|
||||
return __alignof(T);
|
||||
#else
|
||||
#ifndef alignof
|
||||
return __alignof__(T);
|
||||
#else
|
||||
return alignof(T);
|
||||
#endif
|
||||
#endif
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// Lexicographically compare two strings (possibly containing nulls), and
|
||||
// return true if the first is less than the second.
|
||||
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
||||
const char *b_data, uoffset_t b_size) {
|
||||
const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
|
||||
return cmp == 0 ? a_size < b_size : cmp < 0;
|
||||
}
|
||||
|
||||
// When we read serialized data from memory, in the case of most scalars,
|
||||
// we want to just read T, but in the case of Offset, we want to actually
|
||||
// perform the indirection and return a pointer.
|
||||
// The template specialization below does just that.
|
||||
// It is wrapped in a struct since function templates can't overload on the
|
||||
// return type like this.
|
||||
// The typedef is for the convenience of callers of this function
|
||||
// (avoiding the need for a trailing return decltype)
|
||||
template<typename T> struct IndirectHelper {
|
||||
typedef T return_type;
|
||||
typedef T mutable_return_type;
|
||||
static const size_t element_stride = sizeof(T);
|
||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
|
||||
}
|
||||
};
|
||||
template<typename T> struct IndirectHelper<Offset<T>> {
|
||||
typedef const T *return_type;
|
||||
typedef T *mutable_return_type;
|
||||
static const size_t element_stride = sizeof(uoffset_t);
|
||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||
p += i * sizeof(uoffset_t);
|
||||
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
|
||||
}
|
||||
};
|
||||
template<typename T> struct IndirectHelper<const T *> {
|
||||
typedef const T *return_type;
|
||||
typedef T *mutable_return_type;
|
||||
static const size_t element_stride = sizeof(T);
|
||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||
return reinterpret_cast<const T *>(p + i * sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Get a pointer to the the file_identifier section of the buffer.
|
||||
/// @return Returns a const char pointer to the start of the file_identifier
|
||||
/// characters in the buffer. The returned char * has length
|
||||
/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
|
||||
/// This function is UNDEFINED for FlatBuffers whose schema does not include
|
||||
/// a file_identifier (likely points at padding or the start of a the root
|
||||
/// vtable).
|
||||
inline const char *GetBufferIdentifier(const void *buf,
|
||||
bool size_prefixed = false) {
|
||||
return reinterpret_cast<const char *>(buf) +
|
||||
((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
|
||||
}
|
||||
|
||||
// Helper to see if the identifier in a buffer has the expected value.
|
||||
inline bool BufferHasIdentifier(const void *buf, const char *identifier,
|
||||
bool size_prefixed = false) {
|
||||
return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
|
||||
flatbuffers::kFileIdentifierLength) == 0;
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Helpers to get a typed pointer to the root object contained in the buffer.
|
||||
template<typename T> T *GetMutableRoot(void *buf) {
|
||||
EndianCheck();
|
||||
return reinterpret_cast<T *>(
|
||||
reinterpret_cast<uint8_t *>(buf) +
|
||||
EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
|
||||
}
|
||||
|
||||
template<typename T> T *GetMutableSizePrefixedRoot(void *buf) {
|
||||
return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) +
|
||||
sizeof(uoffset_t));
|
||||
}
|
||||
|
||||
template<typename T> const T *GetRoot(const void *buf) {
|
||||
return GetMutableRoot<T>(const_cast<void *>(buf));
|
||||
}
|
||||
|
||||
template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
|
||||
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BUFFER_H_
|
||||
53
include/flatbuffers/buffer_ref.h
Normal file
53
include/flatbuffers/buffer_ref.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_BUFFER_REF_H_
|
||||
#define FLATBUFFERS_BUFFER_REF_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/verifier.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Convenient way to bundle a buffer and its length, to pass it around
|
||||
// typed by its root.
|
||||
// A BufferRef does not own its buffer.
|
||||
struct BufferRefBase {}; // for std::is_base_of
|
||||
|
||||
template<typename T> struct BufferRef : BufferRefBase {
|
||||
BufferRef() : buf(nullptr), len(0), must_free(false) {}
|
||||
BufferRef(uint8_t *_buf, uoffset_t _len)
|
||||
: buf(_buf), len(_len), must_free(false) {}
|
||||
|
||||
~BufferRef() {
|
||||
if (must_free) free(buf);
|
||||
}
|
||||
|
||||
const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
|
||||
|
||||
bool Verify() {
|
||||
Verifier verifier(buf, len);
|
||||
return verifier.VerifyBuffer<T>(nullptr);
|
||||
}
|
||||
|
||||
uint8_t *buf;
|
||||
uoffset_t len;
|
||||
bool must_free;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BUFFER_REF_H_
|
||||
64
include/flatbuffers/default_allocator.h
Normal file
64
include/flatbuffers/default_allocator.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
||||
#define FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
||||
|
||||
#include "flatbuffers/allocator.h"
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// DefaultAllocator uses new/delete to allocate memory regions
|
||||
class DefaultAllocator : public Allocator {
|
||||
public:
|
||||
uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
|
||||
return new uint8_t[size];
|
||||
}
|
||||
|
||||
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
|
||||
|
||||
static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
|
||||
};
|
||||
|
||||
// These functions allow for a null allocator to mean use the default allocator,
|
||||
// as used by DetachedBuffer and vector_downward below.
|
||||
// This is to avoid having a statically or dynamically allocated default
|
||||
// allocator, or having to move it between the classes that may own it.
|
||||
inline uint8_t *Allocate(Allocator *allocator, size_t size) {
|
||||
return allocator ? allocator->allocate(size)
|
||||
: DefaultAllocator().allocate(size);
|
||||
}
|
||||
|
||||
inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
|
||||
if (allocator)
|
||||
allocator->deallocate(p, size);
|
||||
else
|
||||
DefaultAllocator().deallocate(p, size);
|
||||
}
|
||||
|
||||
inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
|
||||
size_t old_size, size_t new_size,
|
||||
size_t in_use_back, size_t in_use_front) {
|
||||
return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
|
||||
in_use_back, in_use_front)
|
||||
: DefaultAllocator().reallocate_downward(
|
||||
old_p, old_size, new_size, in_use_back, in_use_front);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
||||
114
include/flatbuffers/detached_buffer.h
Normal file
114
include/flatbuffers/detached_buffer.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_DETACHED_BUFFER_H_
|
||||
#define FLATBUFFERS_DETACHED_BUFFER_H_
|
||||
|
||||
#include "flatbuffers/allocator.h"
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/default_allocator.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// DetachedBuffer is a finished flatbuffer memory region, detached from its
|
||||
// builder. The original memory region and allocator are also stored so that
|
||||
// the DetachedBuffer can manage the memory lifetime.
|
||||
class DetachedBuffer {
|
||||
public:
|
||||
DetachedBuffer()
|
||||
: allocator_(nullptr),
|
||||
own_allocator_(false),
|
||||
buf_(nullptr),
|
||||
reserved_(0),
|
||||
cur_(nullptr),
|
||||
size_(0) {}
|
||||
|
||||
DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
|
||||
size_t reserved, uint8_t *cur, size_t sz)
|
||||
: allocator_(allocator),
|
||||
own_allocator_(own_allocator),
|
||||
buf_(buf),
|
||||
reserved_(reserved),
|
||||
cur_(cur),
|
||||
size_(sz) {}
|
||||
|
||||
DetachedBuffer(DetachedBuffer &&other)
|
||||
: allocator_(other.allocator_),
|
||||
own_allocator_(other.own_allocator_),
|
||||
buf_(other.buf_),
|
||||
reserved_(other.reserved_),
|
||||
cur_(other.cur_),
|
||||
size_(other.size_) {
|
||||
other.reset();
|
||||
}
|
||||
|
||||
DetachedBuffer &operator=(DetachedBuffer &&other) {
|
||||
if (this == &other) return *this;
|
||||
|
||||
destroy();
|
||||
|
||||
allocator_ = other.allocator_;
|
||||
own_allocator_ = other.own_allocator_;
|
||||
buf_ = other.buf_;
|
||||
reserved_ = other.reserved_;
|
||||
cur_ = other.cur_;
|
||||
size_ = other.size_;
|
||||
|
||||
other.reset();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~DetachedBuffer() { destroy(); }
|
||||
|
||||
const uint8_t *data() const { return cur_; }
|
||||
|
||||
uint8_t *data() { return cur_; }
|
||||
|
||||
size_t size() const { return size_; }
|
||||
|
||||
// These may change access mode, leave these at end of public section
|
||||
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other));
|
||||
FLATBUFFERS_DELETE_FUNC(
|
||||
DetachedBuffer &operator=(const DetachedBuffer &other));
|
||||
|
||||
protected:
|
||||
Allocator *allocator_;
|
||||
bool own_allocator_;
|
||||
uint8_t *buf_;
|
||||
size_t reserved_;
|
||||
uint8_t *cur_;
|
||||
size_t size_;
|
||||
|
||||
inline void destroy() {
|
||||
if (buf_) Deallocate(allocator_, buf_, reserved_);
|
||||
if (own_allocator_ && allocator_) { delete allocator_; }
|
||||
reset();
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
allocator_ = nullptr;
|
||||
own_allocator_ = false;
|
||||
buf_ = nullptr;
|
||||
reserved_ = 0;
|
||||
cur_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_DETACHED_BUFFER_H_
|
||||
1187
include/flatbuffers/flatbuffer_builder.h
Normal file
1187
include/flatbuffers/flatbuffer_builder.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "flatbuffers/bfbs_generator.h"
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
@@ -51,6 +52,7 @@ class FlatCompiler {
|
||||
flatbuffers::IDLOptions::Language lang;
|
||||
const char *generator_help;
|
||||
MakeRuleFn make_rule;
|
||||
BfbsGenerator *bfbs_generator;
|
||||
};
|
||||
|
||||
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
|
||||
|
||||
@@ -155,7 +155,8 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
|
||||
// constant, which here it isn't. Test if memcpy is still faster than
|
||||
// the conditionals in ReadSizedScalar. Can also use inline asm.
|
||||
// clang-format off
|
||||
#if defined(_MSC_VER) && ((defined(_M_X64) && !defined(_M_ARM64EC)) || defined _M_IX86)
|
||||
#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
|
||||
// This is 64-bit Windows only, __movsb does not work on 32-bit Windows.
|
||||
uint64_t u = 0;
|
||||
__movsb(reinterpret_cast<uint8_t *>(&u),
|
||||
reinterpret_cast<const uint8_t *>(data), byte_width);
|
||||
@@ -319,8 +320,8 @@ class FixedTypedVector : public Object {
|
||||
return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
|
||||
}
|
||||
|
||||
Type ElementType() { return type_; }
|
||||
uint8_t size() { return len_; }
|
||||
Type ElementType() const { return type_; }
|
||||
uint8_t size() const { return len_; }
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
@@ -850,6 +851,7 @@ inline Reference Map::operator[](const char *key) const {
|
||||
case 2: comp = KeyCompare<uint16_t>; break;
|
||||
case 4: comp = KeyCompare<uint32_t>; break;
|
||||
case 8: comp = KeyCompare<uint64_t>; break;
|
||||
default: FLATBUFFERS_ASSERT(false); return Reference();
|
||||
}
|
||||
auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
|
||||
if (!res) return Reference(nullptr, 1, NullPackedType());
|
||||
@@ -872,7 +874,7 @@ inline Reference GetRoot(const uint8_t *buffer, size_t size) {
|
||||
}
|
||||
|
||||
inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
|
||||
return GetRoot(flatbuffers::vector_data(buffer), buffer.size());
|
||||
return GetRoot(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
// Flags that configure how the Builder behaves.
|
||||
@@ -1068,7 +1070,16 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
return CreateBlob(data, len, 0, FBT_BLOB);
|
||||
}
|
||||
size_t Blob(const std::vector<uint8_t> &v) {
|
||||
return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB);
|
||||
return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
|
||||
}
|
||||
|
||||
void Blob(const char *key, const void *data, size_t len) {
|
||||
Key(key);
|
||||
Blob(data, len);
|
||||
}
|
||||
void Blob(const char *key, const std::vector<uint8_t> &v) {
|
||||
Key(key);
|
||||
Blob(v);
|
||||
}
|
||||
|
||||
// TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
|
||||
@@ -1086,7 +1097,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
return stack_.size();
|
||||
}
|
||||
|
||||
// TODO(wvo): allow this to specify an aligment greater than the natural
|
||||
// TODO(wvo): allow this to specify an alignment greater than the natural
|
||||
// alignment.
|
||||
size_t EndVector(size_t start, bool typed, bool fixed) {
|
||||
auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed);
|
||||
@@ -1121,27 +1132,24 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
// step automatically when appliccable, and encourage people to write in
|
||||
// sorted fashion.
|
||||
// std::sort is typically already a lot faster on sorted data though.
|
||||
auto dict =
|
||||
reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start);
|
||||
std::sort(dict, dict + len,
|
||||
[&](const TwoValue &a, const TwoValue &b) -> bool {
|
||||
auto as = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(buf_) + a.key.u_);
|
||||
auto bs = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(buf_) + b.key.u_);
|
||||
auto comp = strcmp(as, bs);
|
||||
// We want to disallow duplicate keys, since this results in a
|
||||
// map where values cannot be found.
|
||||
// But we can't assert here (since we don't want to fail on
|
||||
// random JSON input) or have an error mechanism.
|
||||
// Instead, we set has_duplicate_keys_ in the builder to
|
||||
// signal this.
|
||||
// TODO: Have to check for pointer equality, as some sort
|
||||
// implementation apparently call this function with the same
|
||||
// element?? Why?
|
||||
if (!comp && &a != &b) has_duplicate_keys_ = true;
|
||||
return comp < 0;
|
||||
});
|
||||
auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start);
|
||||
std::sort(
|
||||
dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool {
|
||||
auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_);
|
||||
auto bs = reinterpret_cast<const char *>(buf_.data() + b.key.u_);
|
||||
auto comp = strcmp(as, bs);
|
||||
// We want to disallow duplicate keys, since this results in a
|
||||
// map where values cannot be found.
|
||||
// But we can't assert here (since we don't want to fail on
|
||||
// random JSON input) or have an error mechanism.
|
||||
// Instead, we set has_duplicate_keys_ in the builder to
|
||||
// signal this.
|
||||
// TODO: Have to check for pointer equality, as some sort
|
||||
// implementation apparently call this function with the same
|
||||
// element?? Why?
|
||||
if (!comp && &a != &b) has_duplicate_keys_ = true;
|
||||
return comp < 0;
|
||||
});
|
||||
// First create a vector out of all keys.
|
||||
// TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share
|
||||
// the first vector.
|
||||
@@ -1195,7 +1203,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
Vector(elems, len);
|
||||
}
|
||||
template<typename T> void Vector(const std::vector<T> &vec) {
|
||||
Vector(flatbuffers::vector_data(vec), vec.size());
|
||||
Vector(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
template<typename F> size_t TypedVector(F f) {
|
||||
@@ -1397,12 +1405,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
template<typename T> static Type GetScalarType() {
|
||||
static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
|
||||
return flatbuffers::is_floating_point<T>::value
|
||||
? FBT_FLOAT
|
||||
: flatbuffers::is_same<T, bool>::value
|
||||
? FBT_BOOL
|
||||
: (flatbuffers::is_unsigned<T>::value ? FBT_UINT
|
||||
: FBT_INT);
|
||||
return flatbuffers::is_floating_point<T>::value ? FBT_FLOAT
|
||||
: flatbuffers::is_same<T, bool>::value
|
||||
? FBT_BOOL
|
||||
: (flatbuffers::is_unsigned<T>::value ? FBT_UINT : FBT_INT);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1597,10 +1603,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
struct KeyOffsetCompare {
|
||||
explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
||||
bool operator()(size_t a, size_t b) const {
|
||||
auto stra =
|
||||
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
|
||||
auto strb =
|
||||
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b);
|
||||
auto stra = reinterpret_cast<const char *>(buf_->data() + a);
|
||||
auto strb = reinterpret_cast<const char *>(buf_->data() + b);
|
||||
return strcmp(stra, strb) < 0;
|
||||
}
|
||||
const std::vector<uint8_t> *buf_;
|
||||
@@ -1611,10 +1615,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
|
||||
: buf_(&buf) {}
|
||||
bool operator()(const StringOffset &a, const StringOffset &b) const {
|
||||
auto stra = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(*buf_) + a.first);
|
||||
auto strb = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(*buf_) + b.first);
|
||||
auto stra = reinterpret_cast<const char *>(buf_->data() + a.first);
|
||||
auto strb = reinterpret_cast<const char *>(buf_->data() + b.first);
|
||||
return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0;
|
||||
}
|
||||
const std::vector<uint8_t> *buf_;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user