mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acf39ff056 | ||
|
|
0e79e56427 | ||
|
|
aadc4cb8be | ||
|
|
b5ebd3fd78 | ||
|
|
11394575bc | ||
|
|
5b7b36e8be | ||
|
|
c0230d839b | ||
|
|
a8d49f2972 | ||
|
|
416c6020eb | ||
|
|
6d95867a8f | ||
|
|
2eaf790638 | ||
|
|
3b2ced0131 | ||
|
|
00af4e23b3 | ||
|
|
7e00b754f0 | ||
|
|
cf89d1e756 | ||
|
|
ad6054c600 | ||
|
|
c3a01c7228 | ||
|
|
533f75d91b | ||
|
|
fcab80f1bb | ||
|
|
5d2d0b92b1 | ||
|
|
ae6662374d | ||
|
|
7b6c9f4a3c | ||
|
|
5a42b2c76c | ||
|
|
8f625561d0 | ||
|
|
9d2c04d629 | ||
|
|
e000458bb1 | ||
|
|
60975d6f7e | ||
|
|
1cba8b2b49 | ||
|
|
eead6c6219 | ||
|
|
bb9b9dad5f | ||
|
|
ade9e19be0 | ||
|
|
eb1abb51ea | ||
|
|
1fa6091000 | ||
|
|
634c2ee7e3 | ||
|
|
6f895f54c2 | ||
|
|
41d6903294 | ||
|
|
7b038e3277 | ||
|
|
74756e5d1b | ||
|
|
879622fc57 | ||
|
|
83e7a98f69 | ||
|
|
f20b0a45b3 | ||
|
|
207708efef | ||
|
|
225578a8b3 | ||
|
|
459e8acc37 | ||
|
|
8aa8b9139e | ||
|
|
001adf782d | ||
|
|
dbc58ab77c | ||
|
|
2facfeec7e | ||
|
|
4de2814c7b | ||
|
|
37b1acdaff | ||
|
|
a22434e2a1 | ||
|
|
214cc94681 | ||
|
|
a4ff275d9b | ||
|
|
15f32c6907 | ||
|
|
051afd8825 | ||
|
|
728c033ad6 | ||
|
|
4c514483d8 | ||
|
|
c2d9c20803 | ||
|
|
e34ae4c6b6 | ||
|
|
e54536127c | ||
|
|
49d9f941c0 | ||
|
|
cefc21c1f9 | ||
|
|
3e64fa7246 | ||
|
|
b15f3c57ea | ||
|
|
ff802c6802 | ||
|
|
b401957d5f | ||
|
|
8c8151f8f9 | ||
|
|
ebb7c203d3 | ||
|
|
203241ed32 | ||
|
|
ac485609c4 | ||
|
|
de5b85aa66 | ||
|
|
de3df2d88b | ||
|
|
043a24f2e4 | ||
|
|
5a48b0d7d6 | ||
|
|
ce307556fb | ||
|
|
cb616e27cb | ||
|
|
a54ca1e759 | ||
|
|
5b3fadcc16 | ||
|
|
872a497464 | ||
|
|
e301702964 | ||
|
|
f7b734438d | ||
|
|
5792623df4 | ||
|
|
0edb275285 | ||
|
|
acc6a20d39 | ||
|
|
04cd037ba2 | ||
|
|
e1c5db988a | ||
|
|
b80142b901 | ||
|
|
54418f371b | ||
|
|
c92e78a9f8 | ||
|
|
d243b904cc | ||
|
|
374f8fb5fb | ||
|
|
dadbff5714 |
10
.github/labeler.yml
vendored
10
.github/labeler.yml
vendored
@@ -18,6 +18,12 @@ swift:
|
||||
- tests/swift/**
|
||||
- src/idl_gen_swift.cpp
|
||||
|
||||
nim:
|
||||
- '**/*.nim'
|
||||
- nim/**/*
|
||||
- src/idl_gen_nim.cpp
|
||||
- src/bfbs_gen_nim.cpp
|
||||
|
||||
javascript:
|
||||
- '**/*.js'
|
||||
- src/idl_gen_ts.cpp
|
||||
@@ -61,7 +67,7 @@ rust:
|
||||
- '**/*.rs'
|
||||
- rust/**/*
|
||||
- src/idl_gen_rust.cpp
|
||||
|
||||
|
||||
dart:
|
||||
- '**/*.dart'
|
||||
- src/idl_gen_dart.cpp
|
||||
@@ -88,4 +94,4 @@ CI:
|
||||
|
||||
grpc:
|
||||
- grpc/**/*
|
||||
- src/idl_gen_grpc.cpp
|
||||
- src/idl_gen_grpc.cpp
|
||||
|
||||
142
.github/workflows/build.yml
vendored
142
.github/workflows/build.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
cxx: [g++-10, clang++-12]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
- name: build
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
- cxx: g++-10
|
||||
std: 23
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: >
|
||||
CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles"
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
std: [11, 14, 17, 20, 23]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
name: Build Windows 2019
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
name: Build Windows 2017
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
name: Build Windows 2015
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
- name: cmake
|
||||
@@ -195,9 +195,9 @@ jobs:
|
||||
#'-p:EnableSpanT=true,UnsafeByteBuffer=true'
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET Core SDK
|
||||
uses: actions/setup-dotnet@v1.9.0
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '3.1.x'
|
||||
- name: Build
|
||||
@@ -219,34 +219,33 @@ jobs:
|
||||
name: Build Mac (for Intel)
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_FLATC_EXECUTABLE=_build/Release/flatc -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
run: cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
- name: build
|
||||
# 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
|
||||
run: xcodebuild -toolchain clang -configuration Release -target flattests
|
||||
- name: check that the binary is x86_64
|
||||
run: |
|
||||
info=$(file _build/Release/flatc)
|
||||
info=$(file Release/flatc)
|
||||
echo $info
|
||||
echo $info | grep "Mach-O 64-bit executable x86_64"
|
||||
- name: test
|
||||
run: _build/Release/flattests
|
||||
run: Release/flattests
|
||||
- name: make flatc executable
|
||||
run: |
|
||||
chmod +x _build/Release/flatc
|
||||
./_build/Release/flatc --version
|
||||
chmod +x Release/flatc
|
||||
Release/flatc --version
|
||||
- name: flatc tests
|
||||
run: python3 tests/flatc/main.py --flatc ./_build/Release/flatc
|
||||
run: python3 tests/flatc/main.py --flatc Release/flatc
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Mac flatc binary
|
||||
path: _build/Release/flatc
|
||||
path: Release/flatc
|
||||
# Below if only for release.
|
||||
- name: Zip file
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: mv _build/Release/flatc . && zip MacIntel.flatc.binary.zip flatc
|
||||
run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc
|
||||
- name: Release binary
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -265,32 +264,31 @@ jobs:
|
||||
name: Build Mac (universal build)
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_FLATC_EXECUTABLE=_build/Release/flatc -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
- name: build
|
||||
# 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
|
||||
run: xcodebuild -toolchain clang -configuration Release -target flattests
|
||||
- name: check that the binary is "universal"
|
||||
run: |
|
||||
info=$(file _build/Release/flatc)
|
||||
info=$(file Release/flatc)
|
||||
echo $info
|
||||
echo $info | grep "Mach-O universal binary with 2 architectures"
|
||||
- name: test
|
||||
run: _build/Release/flattests
|
||||
run: Release/flattests
|
||||
- name: make flatc executable
|
||||
run: |
|
||||
chmod +x _build/Release/flatc
|
||||
./_build/Release/flatc --version
|
||||
chmod +x Release/flatc
|
||||
Release/flatc --version
|
||||
- name: upload build artifacts
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Mac flatc binary
|
||||
path: _build/Release/flatc
|
||||
path: Release/flatc
|
||||
# Below if only for release.
|
||||
- name: Zip file
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: mv _build/Release/flatc . && zip Mac.flatc.binary.zip flatc
|
||||
run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc
|
||||
- name: Release binary
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -305,11 +303,12 @@ jobs:
|
||||
name: Build Android (on Linux)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- name: set up Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- name: set up flatc
|
||||
run: |
|
||||
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
|
||||
@@ -326,7 +325,7 @@ jobs:
|
||||
matrix:
|
||||
cxx: [g++-10, clang++-12]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
||||
- name: Generate
|
||||
@@ -341,7 +340,7 @@ jobs:
|
||||
matrix:
|
||||
cxx: [g++-10]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: cmake
|
||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
||||
- name: Run benchmarks
|
||||
@@ -356,7 +355,7 @@ jobs:
|
||||
name: Build Java
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: test
|
||||
working-directory: java
|
||||
run: mvn test
|
||||
@@ -366,11 +365,11 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v2
|
||||
uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1.0.5
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt-hotspot'
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- name: Build
|
||||
working-directory: kotlin
|
||||
@@ -381,16 +380,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt-hotspot'
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: gradle/wrapper-validation-action@v1.0.5
|
||||
- name: Build
|
||||
working-directory: kotlin
|
||||
# we are using docker's version of gradle
|
||||
# so no need for wrapper validadation or user
|
||||
# so no need for wrapper validation or user
|
||||
# gradlew
|
||||
run: gradle jvmMainClasses jvmTest jsTest jsBrowserTest
|
||||
|
||||
@@ -398,7 +397,7 @@ jobs:
|
||||
name: Build Rust
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: bash RustTest.sh
|
||||
@@ -407,7 +406,7 @@ jobs:
|
||||
name: Build Python
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: bash PythonTest.sh
|
||||
@@ -416,7 +415,7 @@ jobs:
|
||||
name: Build Go
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: flatc
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
||||
@@ -424,14 +423,30 @@ jobs:
|
||||
working-directory: tests
|
||||
run: bash GoTest.sh
|
||||
|
||||
build-php:
|
||||
name: Build PHP
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: flatc
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
||||
- name: test
|
||||
working-directory: tests
|
||||
run: |
|
||||
php phpTest.php
|
||||
sh phpUnionVectorTest.sh
|
||||
|
||||
build-swift:
|
||||
name: Build Swift
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: test
|
||||
working-directory: tests/swift/tests
|
||||
run: sh SwiftTest.sh
|
||||
run: |
|
||||
swift build --build-tests
|
||||
swift test
|
||||
|
||||
build-swift-wasm:
|
||||
name: Build Swift Wasm
|
||||
@@ -439,9 +454,9 @@ jobs:
|
||||
container:
|
||||
image: ghcr.io/swiftwasm/carton:0.15.3
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Wasmer
|
||||
uses: wasmerio/setup-wasmer@v1
|
||||
uses: wasmerio/setup-wasmer@v2
|
||||
- name: Test
|
||||
working-directory: tests/swift/Wasm.tests
|
||||
run: carton test
|
||||
@@ -450,7 +465,7 @@ jobs:
|
||||
name: Build TS
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: flatc
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
||||
@@ -466,7 +481,7 @@ jobs:
|
||||
name: Build Dart
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dart-lang/setup-dart@v1
|
||||
with:
|
||||
sdk: stable
|
||||
@@ -477,6 +492,22 @@ jobs:
|
||||
working-directory: tests
|
||||
run: bash DartTest.sh
|
||||
|
||||
build-nim:
|
||||
name: Build Nim
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: flatc
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
||||
- uses: jiro4989/setup-nim-action@v1
|
||||
- name: install library
|
||||
working-directory: nim
|
||||
run: nimble -y develop
|
||||
- name: test
|
||||
working-directory: tests/nim
|
||||
run: python3 testnim.py
|
||||
|
||||
release-digests:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
|
||||
@@ -508,7 +539,8 @@ jobs:
|
||||
actions: read # To read the workflow path.
|
||||
id-token: write # To sign the provenance.
|
||||
contents: write # To add assets to a release.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.1
|
||||
with:
|
||||
base64-subjects: "${{ needs.release-digests.outputs.digests }}"
|
||||
upload-assets: true # Optional: Upload to a new release
|
||||
compile-generator: true # Workaround for https://github.com/slsa-framework/slsa-github-generator/issues/1163
|
||||
|
||||
106
.github/workflows/release.yml
vendored
Normal file
106
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
name: Release
|
||||
permissions: read-all
|
||||
|
||||
on:
|
||||
# For manual tests.
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
publish-npm:
|
||||
name: Publish NPM
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
publish-pypi:
|
||||
name: Publish PyPi
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./python
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install setuptools wheel twine
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
python3 setup.py sdist bdist_wheel
|
||||
|
||||
- name: Upload to PyPi
|
||||
run: |
|
||||
python3 -m twine upload dist/*
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }}
|
||||
|
||||
publish-nuget:
|
||||
name: Publish NuGet
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./net/flatbuffers
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build Google.FlatBuffers.csproj -c Release
|
||||
|
||||
- name: Pack
|
||||
run: |
|
||||
dotnet pack Google.FlatBuffers.csproj -c Release
|
||||
|
||||
- name: Upload to NuGet
|
||||
run: |
|
||||
dotnet nuget push .\bin\Release\Google.FlatBuffers.*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
|
||||
|
||||
publish-maven:
|
||||
name: Publish Maven
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./java
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Maven Central Repository
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
cache: 'maven'
|
||||
server-id: ossrh
|
||||
server-username: OSSRH_USERNAME
|
||||
server-password: OSSRH_PASSWORD
|
||||
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var
|
||||
|
||||
- name: Publish Maven
|
||||
run: mvn --batch-mode clean deploy
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
|
||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
|
||||
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -149,4 +149,5 @@ flatbuffers.pc
|
||||
**/html/**
|
||||
**/latex/**
|
||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR
|
||||
cmake-build-debug/
|
||||
_deps/
|
||||
|
||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -4,6 +4,18 @@ All major or breaking changes will be documented in this file, as well as any
|
||||
new features that should be highlighted. Minor fixes or improvements are not
|
||||
necessarily listed.
|
||||
|
||||
## 22.12.06 (Dec 06 2022)
|
||||
|
||||
* Bug fixing release, no major changes.
|
||||
|
||||
## 22.10.25 (Oct 25 2022)
|
||||
|
||||
* Added Nim language support with generator and runtime libraries (#7534).
|
||||
|
||||
## 22.9.29 (Sept 29 2022)
|
||||
|
||||
* Rust soundness fixes to avoid the crate from bing labelled unsafe (#7518).
|
||||
|
||||
## 22.9.24 (Sept 24 2022)
|
||||
|
||||
* 20 Major releases in a row? Nope, we switched to a new
|
||||
@@ -23,8 +35,8 @@ necessarily listed.
|
||||
`AlignOf()` for structs (#7520).
|
||||
|
||||
* C# has an
|
||||
[offical Nuget package](https://www.nuget.org/packages/Google.FlatBuffers) now
|
||||
(#7496).
|
||||
[official Nuget package](https://www.nuget.org/packages/Google.FlatBuffers)
|
||||
now (#7496).
|
||||
|
||||
## 2.0.8 (Aug 29 2022)
|
||||
|
||||
|
||||
@@ -1,37 +1,39 @@
|
||||
set(VERSION_MAJOR 22)
|
||||
set(VERSION_MINOR 9)
|
||||
set(VERSION_PATCH 24)
|
||||
set(VERSION_MINOR 12)
|
||||
set(VERSION_PATCH 06)
|
||||
set(VERSION_COMMIT 0)
|
||||
|
||||
find_program(GIT git)
|
||||
if(GIT AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
||||
execute_process(
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
||||
find_program(GIT git)
|
||||
if(GIT)
|
||||
execute_process(
|
||||
COMMAND ${GIT} describe --tags
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE GIT_DESCRIBE_RESULT
|
||||
)
|
||||
)
|
||||
|
||||
if(GIT_DESCRIBE_RESULT EQUAL 0)
|
||||
# Test if the most recent Git tag matches the pattern "v<major>.<minor>.<patch>*"
|
||||
if(GIT_DESCRIBE_DIRTY MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+.*")
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
|
||||
# If the tag points to the commit, then only the tag is shown in "git describe"
|
||||
if(VERSION_COMMIT STREQUAL GIT_DESCRIBE_DIRTY)
|
||||
set(VERSION_COMMIT 0)
|
||||
if(GIT_DESCRIBE_RESULT EQUAL 0)
|
||||
# Test if the most recent Git tag matches the pattern "v<major>.<minor>.<patch>*"
|
||||
if(GIT_DESCRIBE_DIRTY MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+.*")
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
|
||||
# If the tag points to the commit, then only the tag is shown in "git describe"
|
||||
if(VERSION_COMMIT STREQUAL GIT_DESCRIBE_DIRTY)
|
||||
set(VERSION_COMMIT 0)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "\"${GIT_DESCRIBE_DIRTY}\" does not match pattern v<major>.<minor>.<patch>-<commit>")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "\"${GIT_DESCRIBE_DIRTY}\" does not match pattern v<major>.<minor>.<patch>-<commit>")
|
||||
message(WARNING "git describe failed with exit code: ${GIT_DESCRIBE_RESULT}")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "git describe failed with exit code: ${GIT_DESCRIBE_RESULT}")
|
||||
message(WARNING "git is not found")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "git is not found")
|
||||
endif()
|
||||
|
||||
message(STATUS "Proceeding with version: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_COMMIT}")
|
||||
|
||||
@@ -71,10 +71,10 @@ option(FLATBUFFERS_ENABLE_PCH
|
||||
Only work if CMake supports 'target_precompile_headers'. \"
|
||||
This can speed up compilation time."
|
||||
OFF)
|
||||
option(FLATBUFFERS_SKIP_MONSTER_EXTRA
|
||||
option(FLATBUFFERS_SKIP_MONSTER_EXTRA
|
||||
"Skip generating monster_extra.fbs that contains non-supported numerical\"
|
||||
types." OFF)
|
||||
option(FLATBUFFERS_STRICT_MODE
|
||||
option(FLATBUFFERS_STRICT_MODE
|
||||
"Build flatbuffers with all warnings as errors (-Werror or /WX)."
|
||||
OFF)
|
||||
|
||||
@@ -125,6 +125,13 @@ if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
endif()
|
||||
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||
|
||||
if(NOT WIN32)
|
||||
check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH)
|
||||
if(NOT HAVE_REALPATH)
|
||||
add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/allocator.h
|
||||
include/flatbuffers/array.h
|
||||
@@ -182,6 +189,7 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/flatc_main.cpp
|
||||
src/bfbs_gen.h
|
||||
src/bfbs_gen_lua.h
|
||||
src/bfbs_gen_nim.h
|
||||
src/bfbs_namer.h
|
||||
include/flatbuffers/code_generators.h
|
||||
src/binary_annotator.h
|
||||
@@ -189,6 +197,7 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/annotated_binary_text_gen.h
|
||||
src/annotated_binary_text_gen.cpp
|
||||
src/bfbs_gen_lua.cpp
|
||||
src/bfbs_gen_nim.cpp
|
||||
src/code_generators.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
@@ -217,6 +226,7 @@ set(FlatBuffers_Tests_SRCS
|
||||
tests/flexbuffers_test.cpp
|
||||
tests/fuzz_test.cpp
|
||||
tests/json_test.cpp
|
||||
tests/key_field_test.cpp
|
||||
tests/monster_test.cpp
|
||||
tests/optional_scalars_test.cpp
|
||||
tests/parser_test.cpp
|
||||
@@ -255,6 +265,8 @@ set(FlatBuffers_Tests_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/native_inline_table_test_generated.h
|
||||
# file generate by running compiler on tests/alignment_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/alignment_test_generated.h
|
||||
# file generate by running compiler on tests/key_field/key_field_sample.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/key_field/key_field_sample_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Tests_CPP17_SRCS
|
||||
@@ -356,8 +368,8 @@ include_directories(grpc)
|
||||
|
||||
# Creates an interface library that stores the configuration settings that each
|
||||
# target links too. This is a compromise between setting configuration globally
|
||||
# with add_compile_options() and the more targetted target_compile_options().
|
||||
# This way each target in this file can share settings and override them if
|
||||
# with add_compile_options() and the more targetted target_compile_options().
|
||||
# This way each target in this file can share settings and override them if
|
||||
# needed.
|
||||
add_library(ProjectConfig INTERFACE)
|
||||
target_compile_features(ProjectConfig
|
||||
@@ -373,7 +385,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC_LIKE)
|
||||
target_compile_options(ProjectConfig
|
||||
INTERFACE
|
||||
INTERFACE
|
||||
/W4
|
||||
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
|
||||
/WX # Treat all compiler warnings as errors
|
||||
@@ -405,8 +417,8 @@ else()
|
||||
-Wno-error=stringop-overflow
|
||||
>
|
||||
>
|
||||
-pedantic
|
||||
-Wextra
|
||||
-pedantic
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
-Wold-style-cast
|
||||
-fsigned-char
|
||||
@@ -420,7 +432,7 @@ else()
|
||||
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,3.8>:
|
||||
-Wimplicit-fallthrough
|
||||
-Wextra-semi
|
||||
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
|
||||
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
|
||||
-Werror=unused-private-field
|
||||
>
|
||||
>
|
||||
@@ -429,7 +441,7 @@ else()
|
||||
$<$<CXX_COMPILER_ID:GNU>:
|
||||
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,4.4>:
|
||||
-Wunused-result
|
||||
-Wunused-parameter
|
||||
-Wunused-parameter
|
||||
-Werror=unused-parameter
|
||||
-Wmissing-declarations
|
||||
>
|
||||
@@ -437,7 +449,7 @@ else()
|
||||
-Wzero-as-null-pointer-constant
|
||||
>
|
||||
$<$<VERSION_GREATER:$<CXX_COMPILER_VERSION>,7.0>:
|
||||
-faligned-new
|
||||
-faligned-new
|
||||
$<$<BOOL:${FLATBUFFERS_STRICT_MODE}>:
|
||||
-Werror=implicit-fallthrough=2
|
||||
>
|
||||
@@ -467,7 +479,7 @@ if(FLATBUFFERS_BUILD_FLATLIB)
|
||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||
|
||||
# Attach header directory for when build via add_subdirectory().
|
||||
target_include_directories(flatbuffers
|
||||
target_include_directories(flatbuffers
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
)
|
||||
@@ -485,7 +497,7 @@ if(FLATBUFFERS_BUILD_FLATC)
|
||||
endif()
|
||||
|
||||
target_link_libraries(flatc PRIVATE $<BUILD_INTERFACE:ProjectConfig>)
|
||||
target_compile_options(flatc
|
||||
target_compile_options(flatc
|
||||
PUBLIC
|
||||
$<$<AND:$<BOOL:${MSVC_LIKE}>,$<CONFIG:Release>>:
|
||||
/MT
|
||||
@@ -576,7 +588,7 @@ function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
-b --schema --bfbs-comments --bfbs-builtins
|
||||
--bfbs-filenames ${SRC_FBS_DIR}
|
||||
--bfbs-filenames "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS_DIR}"
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
@@ -620,7 +632,7 @@ if(FLATBUFFERS_BUILD_TESTS)
|
||||
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test1.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/namespace_test/namespace_test2.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/union_vector/union_vector.fbs "--no-includes;--gen-compare;--gen-name-strings")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/union_vector/union_vector.fbs "--no-includes;--gen-compare;")
|
||||
compile_flatbuffers_schema_to_cpp(tests/optional_scalars.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
|
||||
@@ -628,6 +640,7 @@ if(FLATBUFFERS_BUILD_TESTS)
|
||||
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
|
||||
compile_flatbuffers_schema_to_cpp(tests/native_inline_table_test.fbs "--gen-compare")
|
||||
compile_flatbuffers_schema_to_cpp(tests/alignment_test.fbs "--gen-compare")
|
||||
compile_flatbuffers_schema_to_cpp(tests/key_field/key_field_sample.fbs)
|
||||
if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
|
||||
endif()
|
||||
@@ -687,13 +700,13 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
find_package(gRPC CONFIG REQUIRED)
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
add_dependencies(grpctest generated_code)
|
||||
target_link_libraries(grpctext
|
||||
PRIVATE
|
||||
target_link_libraries(grpctext
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:ProjectConfig>
|
||||
gRPC::grpc++_unsecure
|
||||
gRPC::gpr
|
||||
gRPC::grpc++_unsecure
|
||||
gRPC::gpr
|
||||
pthread
|
||||
dl
|
||||
dl
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -706,8 +719,8 @@ if(FLATBUFFERS_INSTALL)
|
||||
|
||||
configure_file(CMake/flatbuffers-config-version.cmake.in flatbuffers-config-version.cmake @ONLY)
|
||||
install(
|
||||
FILES
|
||||
"CMake/flatbuffers-config.cmake"
|
||||
FILES
|
||||
"CMake/flatbuffers-config.cmake"
|
||||
"CMake/BuildFlatBuffers.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-config-version.cmake"
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'FlatBuffers'
|
||||
s.version = '22.9.24'
|
||||
s.version = '22.12.06'
|
||||
s.summary = 'FlatBuffers: Memory Efficient Serialization Library'
|
||||
|
||||
s.description = "FlatBuffers is a cross platform serialization library architected for
|
||||
@@ -11,11 +11,11 @@ Pod::Spec.new do |s|
|
||||
s.homepage = 'https://github.com/google/flatbuffers'
|
||||
s.license = { :type => 'Apache2.0', :file => 'LICENSE' }
|
||||
s.author = { 'mustii' => 'mustii@mmk.one' }
|
||||
s.source = { :git => 'https://github.com/mustiikhalil/flatbuffers.git', :tag => s.version.to_s, :submodules => true }
|
||||
s.source = { :git => 'https://github.com/google/flatbuffers.git', :tag => s.version.to_s, :submodules => true }
|
||||
|
||||
s.ios.deployment_target = '11.0'
|
||||
s.osx.deployment_target = '10.14'
|
||||
|
||||
s.swift_version = '5.0'
|
||||
s.source_files = 'Sources/Flatbuffers/*.swift'
|
||||
s.source_files = 'swift/Sources/Flatbuffers/*.swift'
|
||||
end
|
||||
@@ -32,5 +32,6 @@ let package = Package(
|
||||
.target(
|
||||
name: "FlatBuffers",
|
||||
dependencies: [],
|
||||
path: "swift/Sources",
|
||||
exclude: ["Documentation.docc/Resources/code/swift"]),
|
||||
])
|
||||
@@ -31,6 +31,7 @@ let package = Package(
|
||||
targets: [
|
||||
.target(
|
||||
name: "FlatBuffers",
|
||||
dependencies: []),
|
||||
dependencies: [],
|
||||
path: "swift/Sources")
|
||||
])
|
||||
|
||||
@@ -33,10 +33,10 @@ swift_rules_extra_dependencies()
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "16e9fca53ed6bd4ff4ad76facc9b7b651a89db1689a2877d6fd7b82aa824e366",
|
||||
sha256 = "ae013bf35bd23234d1dea46b079f1e05ba74ac0321423830119d3e787ec73483",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.36.0/rules_go-v0.36.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.36.0/rules_go-v0.36.0.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.FlatBufferTest">
|
||||
|
||||
<uses-sdk android:minSdkVersion="14"/>
|
||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||
|
||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||
|
||||
@@ -36,7 +36,7 @@ class Animal : Table() {
|
||||
return if(o != 0) bb.getShort(o + bb_pos).toUShort() else 0u
|
||||
}
|
||||
companion object {
|
||||
fun validateVersion() = Constants.FLATBUFFERS_22_9_24()
|
||||
fun validateVersion() = Constants.FLATBUFFERS_22_12_06()
|
||||
fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal())
|
||||
fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal {
|
||||
_bb.order(ByteOrder.LITTLE_ENDIAN)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: flat_buffers
|
||||
version: 22.9.24
|
||||
version: 22.12.06
|
||||
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
|
||||
|
||||
207
dart/test/bool_structs_generated.dart
Normal file
207
dart/test/bool_structs_generated.dart
Normal file
@@ -0,0 +1,207 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
|
||||
class Foo {
|
||||
Foo._(this._bc, this._bcOffset);
|
||||
factory Foo(List<int> bytes) {
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Foo> reader = _FooReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
FooProperties? get myFoo => FooProperties.reader.vTableGetNullable(_bc, _bcOffset, 4);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Foo{myFoo: ${myFoo}}';
|
||||
}
|
||||
|
||||
FooT unpack() => FooT(
|
||||
myFoo: myFoo?.unpack());
|
||||
|
||||
static int pack(fb.Builder fbBuilder, FooT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class FooT implements fb.Packable {
|
||||
FooPropertiesT? myFoo;
|
||||
|
||||
FooT({
|
||||
this.myFoo});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(1);
|
||||
if (myFoo != null) {
|
||||
fbBuilder.addStruct(0, myFoo!.pack(fbBuilder));
|
||||
}
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FooT{myFoo: ${myFoo}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _FooReader extends fb.TableReader<Foo> {
|
||||
const _FooReader();
|
||||
|
||||
@override
|
||||
Foo createObject(fb.BufferContext bc, int offset) =>
|
||||
Foo._(bc, offset);
|
||||
}
|
||||
|
||||
class FooBuilder {
|
||||
FooBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable(1);
|
||||
}
|
||||
|
||||
int addMyFoo(int offset) {
|
||||
fbBuilder.addStruct(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class FooObjectBuilder extends fb.ObjectBuilder {
|
||||
final FooPropertiesObjectBuilder? _myFoo;
|
||||
|
||||
FooObjectBuilder({
|
||||
FooPropertiesObjectBuilder? myFoo,
|
||||
})
|
||||
: _myFoo = myFoo;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.startTable(1);
|
||||
if (_myFoo != null) {
|
||||
fbBuilder.addStruct(0, _myFoo!.finish(fbBuilder));
|
||||
}
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class FooProperties {
|
||||
FooProperties._(this._bc, this._bcOffset);
|
||||
|
||||
static const fb.Reader<FooProperties> reader = _FooPropertiesReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
bool get a => const fb.BoolReader().read(_bc, _bcOffset + 0);
|
||||
bool get b => const fb.BoolReader().read(_bc, _bcOffset + 1);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FooProperties{a: ${a}, b: ${b}}';
|
||||
}
|
||||
|
||||
FooPropertiesT unpack() => FooPropertiesT(
|
||||
a: a,
|
||||
b: b);
|
||||
|
||||
static int pack(fb.Builder fbBuilder, FooPropertiesT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class FooPropertiesT implements fb.Packable {
|
||||
bool a;
|
||||
bool b;
|
||||
|
||||
FooPropertiesT({
|
||||
required this.a,
|
||||
required this.b});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
fbBuilder.putBool(b);
|
||||
fbBuilder.putBool(a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FooPropertiesT{a: ${a}, b: ${b}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _FooPropertiesReader extends fb.StructReader<FooProperties> {
|
||||
const _FooPropertiesReader();
|
||||
|
||||
@override
|
||||
int get size => 2;
|
||||
|
||||
@override
|
||||
FooProperties createObject(fb.BufferContext bc, int offset) =>
|
||||
FooProperties._(bc, offset);
|
||||
}
|
||||
|
||||
class FooPropertiesBuilder {
|
||||
FooPropertiesBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
int finish(bool a, bool b) {
|
||||
fbBuilder.putBool(b);
|
||||
fbBuilder.putBool(a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FooPropertiesObjectBuilder extends fb.ObjectBuilder {
|
||||
final bool _a;
|
||||
final bool _b;
|
||||
|
||||
FooPropertiesObjectBuilder({
|
||||
required bool a,
|
||||
required bool b,
|
||||
})
|
||||
: _a = a,
|
||||
_b = b;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.putBool(_b);
|
||||
fbBuilder.putBool(_a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,10 @@ class CheckOtherLangaugesData {
|
||||
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
|
||||
'nativeInline: null, '
|
||||
'longEnumNonEnumDefault: LongEnum{value: 0}, '
|
||||
'longEnumNormalDefault: LongEnum{value: 2}}, '
|
||||
'longEnumNormalDefault: LongEnum{value: 2}, nanDefault: NaN, '
|
||||
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
|
||||
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
|
||||
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
|
||||
'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
|
||||
'testarrayofstring: [test1, test2], testarrayoftables: null, '
|
||||
'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
|
||||
@@ -110,7 +113,10 @@ class CheckOtherLangaugesData {
|
||||
'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
|
||||
'nativeInline: null, '
|
||||
'longEnumNonEnumDefault: LongEnum{value: 0}, '
|
||||
'longEnumNormalDefault: LongEnum{value: 2}}, '
|
||||
'longEnumNormalDefault: LongEnum{value: 2}, nanDefault: NaN, '
|
||||
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
|
||||
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
|
||||
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, '
|
||||
'testnestedflatbuffer: null, testempty: null, testbool: true, '
|
||||
'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, '
|
||||
'testhashs64Fnv1: 7930699090847568257, '
|
||||
@@ -137,7 +143,10 @@ class CheckOtherLangaugesData {
|
||||
'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
|
||||
'nativeInline: Test{a: 1, b: 2}, '
|
||||
'longEnumNonEnumDefault: LongEnum{value: 0}, '
|
||||
'longEnumNormalDefault: LongEnum{value: 2}}',
|
||||
'longEnumNormalDefault: LongEnum{value: 2}, nanDefault: NaN, '
|
||||
'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: '
|
||||
'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: '
|
||||
'-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
109
dart/test/include_test1_generated.dart
Normal file
109
dart/test/include_test1_generated.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
|
||||
import './include_test2_my_game.other_name_space_generated.dart' as my_game_other_name_space;
|
||||
|
||||
class TableA {
|
||||
TableA._(this._bc, this._bcOffset);
|
||||
factory TableA(List<int> bytes) {
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<TableA> reader = _TableAReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
my_game_other_name_space.TableB? get b => my_game_other_name_space.TableB.reader.vTableGetNullable(_bc, _bcOffset, 4);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TableA{b: ${b}}';
|
||||
}
|
||||
|
||||
TableAT unpack() => TableAT(
|
||||
b: b?.unpack());
|
||||
|
||||
static int pack(fb.Builder fbBuilder, TableAT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class TableAT implements fb.Packable {
|
||||
my_game_other_name_space.TableBT? b;
|
||||
|
||||
TableAT({
|
||||
this.b});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
final int? bOffset = b?.pack(fbBuilder);
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, bOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TableAT{b: ${b}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _TableAReader extends fb.TableReader<TableA> {
|
||||
const _TableAReader();
|
||||
|
||||
@override
|
||||
TableA createObject(fb.BufferContext bc, int offset) =>
|
||||
TableA._(bc, offset);
|
||||
}
|
||||
|
||||
class TableABuilder {
|
||||
TableABuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable(1);
|
||||
}
|
||||
|
||||
int addBOffset(int? offset) {
|
||||
fbBuilder.addOffset(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class TableAObjectBuilder extends fb.ObjectBuilder {
|
||||
final my_game_other_name_space.TableBObjectBuilder? _b;
|
||||
|
||||
TableAObjectBuilder({
|
||||
my_game_other_name_space.TableBObjectBuilder? b,
|
||||
})
|
||||
: _b = b;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
final int? bOffset = _b?.getOrCreateOffset(fbBuilder);
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, bOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
241
dart/test/include_test2_my_game.other_name_space_generated.dart
Normal file
241
dart/test/include_test2_my_game.other_name_space_generated.dart
Normal file
@@ -0,0 +1,241 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
library my_game.other_name_space;
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
|
||||
import './include_test1_generated.dart';
|
||||
|
||||
class FromInclude {
|
||||
final int value;
|
||||
const FromInclude._(this.value);
|
||||
|
||||
factory FromInclude.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum FromInclude');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static FromInclude? _createOrNull(int? value) =>
|
||||
value == null ? null : FromInclude.fromValue(value);
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 0;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const FromInclude IncludeVal = FromInclude._(0);
|
||||
static const Map<int, FromInclude> values = {
|
||||
0: IncludeVal};
|
||||
|
||||
static const fb.Reader<FromInclude> reader = _FromIncludeReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FromInclude{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _FromIncludeReader extends fb.Reader<FromInclude> {
|
||||
const _FromIncludeReader();
|
||||
|
||||
@override
|
||||
int get size => 8;
|
||||
|
||||
@override
|
||||
FromInclude read(fb.BufferContext bc, int offset) =>
|
||||
FromInclude.fromValue(const fb.Int64Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Unused {
|
||||
Unused._(this._bc, this._bcOffset);
|
||||
|
||||
static const fb.Reader<Unused> reader = _UnusedReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
int get a => const fb.Int32Reader().read(_bc, _bcOffset + 0);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Unused{a: ${a}}';
|
||||
}
|
||||
|
||||
UnusedT unpack() => UnusedT(
|
||||
a: a);
|
||||
|
||||
static int pack(fb.Builder fbBuilder, UnusedT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class UnusedT implements fb.Packable {
|
||||
int a;
|
||||
|
||||
UnusedT({
|
||||
required this.a});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
fbBuilder.putInt32(a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UnusedT{a: ${a}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _UnusedReader extends fb.StructReader<Unused> {
|
||||
const _UnusedReader();
|
||||
|
||||
@override
|
||||
int get size => 4;
|
||||
|
||||
@override
|
||||
Unused createObject(fb.BufferContext bc, int offset) =>
|
||||
Unused._(bc, offset);
|
||||
}
|
||||
|
||||
class UnusedBuilder {
|
||||
UnusedBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
int finish(int a) {
|
||||
fbBuilder.putInt32(a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UnusedObjectBuilder extends fb.ObjectBuilder {
|
||||
final int _a;
|
||||
|
||||
UnusedObjectBuilder({
|
||||
required int a,
|
||||
})
|
||||
: _a = a;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
fbBuilder.putInt32(_a);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class TableB {
|
||||
TableB._(this._bc, this._bcOffset);
|
||||
factory TableB(List<int> bytes) {
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<TableB> reader = _TableBReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
TableA? get a => TableA.reader.vTableGetNullable(_bc, _bcOffset, 4);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TableB{a: ${a}}';
|
||||
}
|
||||
|
||||
TableBT unpack() => TableBT(
|
||||
a: a?.unpack());
|
||||
|
||||
static int pack(fb.Builder fbBuilder, TableBT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class TableBT implements fb.Packable {
|
||||
TableAT? a;
|
||||
|
||||
TableBT({
|
||||
this.a});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
final int? aOffset = a?.pack(fbBuilder);
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, aOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TableBT{a: ${a}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _TableBReader extends fb.TableReader<TableB> {
|
||||
const _TableBReader();
|
||||
|
||||
@override
|
||||
TableB createObject(fb.BufferContext bc, int offset) =>
|
||||
TableB._(bc, offset);
|
||||
}
|
||||
|
||||
class TableBBuilder {
|
||||
TableBBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable(1);
|
||||
}
|
||||
|
||||
int addAOffset(int? offset) {
|
||||
fbBuilder.addOffset(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class TableBObjectBuilder extends fb.ObjectBuilder {
|
||||
final TableAObjectBuilder? _a;
|
||||
|
||||
TableBObjectBuilder({
|
||||
TableAObjectBuilder? a,
|
||||
})
|
||||
: _a = a;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
final int? aOffset = _a?.getOrCreateOffset(fbBuilder);
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, aOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
155
dart/test/list_of_enums_generated.dart
Normal file
155
dart/test/list_of_enums_generated.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
|
||||
class OptionsEnum {
|
||||
final int value;
|
||||
const OptionsEnum._(this.value);
|
||||
|
||||
factory OptionsEnum.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum OptionsEnum');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static OptionsEnum? _createOrNull(int? value) =>
|
||||
value == null ? null : OptionsEnum.fromValue(value);
|
||||
|
||||
static const int minValue = 1;
|
||||
static const int maxValue = 3;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const OptionsEnum A = OptionsEnum._(1);
|
||||
static const OptionsEnum B = OptionsEnum._(2);
|
||||
static const OptionsEnum C = OptionsEnum._(3);
|
||||
static const Map<int, OptionsEnum> values = {
|
||||
1: A,
|
||||
2: B,
|
||||
3: C};
|
||||
|
||||
static const fb.Reader<OptionsEnum> reader = _OptionsEnumReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OptionsEnum{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _OptionsEnumReader extends fb.Reader<OptionsEnum> {
|
||||
const _OptionsEnumReader();
|
||||
|
||||
@override
|
||||
int get size => 4;
|
||||
|
||||
@override
|
||||
OptionsEnum read(fb.BufferContext bc, int offset) =>
|
||||
OptionsEnum.fromValue(const fb.Uint32Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class MyTable {
|
||||
MyTable._(this._bc, this._bcOffset);
|
||||
factory MyTable(List<int> bytes) {
|
||||
final rootRef = fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<MyTable> reader = _MyTableReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
List<OptionsEnum>? get options => const fb.ListReader<OptionsEnum>(OptionsEnum.reader).vTableGetNullable(_bc, _bcOffset, 4);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MyTable{options: ${options}}';
|
||||
}
|
||||
|
||||
MyTableT unpack() => MyTableT(
|
||||
options: const fb.ListReader<OptionsEnum>(OptionsEnum.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 4));
|
||||
|
||||
static int pack(fb.Builder fbBuilder, MyTableT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class MyTableT implements fb.Packable {
|
||||
List<OptionsEnum>? options;
|
||||
|
||||
MyTableT({
|
||||
this.options});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
final int? optionsOffset = options == null ? null
|
||||
: fbBuilder.writeListUint32(options!.map((f) => f.value).toList());
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, optionsOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MyTableT{options: ${options}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _MyTableReader extends fb.TableReader<MyTable> {
|
||||
const _MyTableReader();
|
||||
|
||||
@override
|
||||
MyTable createObject(fb.BufferContext bc, int offset) =>
|
||||
MyTable._(bc, offset);
|
||||
}
|
||||
|
||||
class MyTableBuilder {
|
||||
MyTableBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable(1);
|
||||
}
|
||||
|
||||
int addOptionsOffset(int? offset) {
|
||||
fbBuilder.addOffset(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class MyTableObjectBuilder extends fb.ObjectBuilder {
|
||||
final List<OptionsEnum>? _options;
|
||||
|
||||
MyTableObjectBuilder({
|
||||
List<OptionsEnum>? options,
|
||||
})
|
||||
: _options = options;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
final int? optionsOffset = _options == null ? null
|
||||
: fbBuilder.writeListUint32(_options!.map((f) => f.value).toList());
|
||||
fbBuilder.startTable(1);
|
||||
fbBuilder.addOffset(0, optionsOffset);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,14 @@ enum Race:byte {
|
||||
Elf,
|
||||
}
|
||||
|
||||
enum LongEnum:ulong (bit_flags) {
|
||||
LongOne = 1,
|
||||
LongTwo = 2,
|
||||
// Because this is a bitflag, 40 will be out of range of a 32-bit integer,
|
||||
// allowing us to exercise any logic special to big numbers.
|
||||
LongBig = 40,
|
||||
}
|
||||
|
||||
union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster }
|
||||
|
||||
union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster }
|
||||
@@ -62,6 +70,10 @@ struct StructOfStructs {
|
||||
c: Ability;
|
||||
}
|
||||
|
||||
struct StructOfStructsOfStructs {
|
||||
a: StructOfStructs;
|
||||
}
|
||||
|
||||
table Stat {
|
||||
id:string;
|
||||
val:long;
|
||||
@@ -124,6 +136,20 @@ table Monster {
|
||||
signed_enum:Race = None (id:48);
|
||||
testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster");
|
||||
scalar_key_sorted_tables:[Stat] (id: 50);
|
||||
native_inline:Test (id: 51, native_inline);
|
||||
// The default value of this enum will be a numeric zero, which isn't a valid
|
||||
// enum value.
|
||||
long_enum_non_enum_default:LongEnum (id: 52);
|
||||
long_enum_normal_default:LongEnum = LongOne (id: 53);
|
||||
// Test that default values nan and +/-inf work.
|
||||
nan_default:float = nan (id: 54);
|
||||
inf_default:float = inf (id: 55);
|
||||
positive_inf_default:float = +inf (id: 56);
|
||||
infinity_default:float = infinity (id: 57);
|
||||
positive_infinity_default:float = +infinity (id: 58);
|
||||
negative_inf_default:float = -inf (id: 59);
|
||||
negative_infinity_default:float = -infinity (id: 60);
|
||||
double_inf_default:double = inf (id: 61);
|
||||
}
|
||||
|
||||
table TypeAliases {
|
||||
|
||||
@@ -9,6 +9,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_test_my_game_generated.dart' as my_game;
|
||||
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||
|
||||
import './include_test1_generated.dart';
|
||||
|
||||
class Monster {
|
||||
Monster._(this._bc, this._bcOffset);
|
||||
factory Monster(List<int> bytes) {
|
||||
|
||||
@@ -9,6 +9,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_test_my_game_generated.dart' as my_game;
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
|
||||
import './include_test1_generated.dart';
|
||||
|
||||
/// Composite components of Monster color.
|
||||
class Color {
|
||||
final int value;
|
||||
@@ -17,7 +19,11 @@ class Color {
|
||||
factory Color.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum Color');
|
||||
if (value == 0) {
|
||||
return Color._(0);
|
||||
} else {
|
||||
throw StateError('Invalid value $value for bit flag enum Color');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -66,7 +72,7 @@ class Race {
|
||||
factory Race.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum Race');
|
||||
throw StateError('Invalid value $value for bit flag enum Race');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -107,6 +113,54 @@ class _RaceReader extends fb.Reader<Race> {
|
||||
Race.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class LongEnum {
|
||||
final int value;
|
||||
const LongEnum._(this.value);
|
||||
|
||||
factory LongEnum.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
if (value == 0) {
|
||||
return LongEnum._(0);
|
||||
} else {
|
||||
throw StateError('Invalid value $value for bit flag enum LongEnum');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static LongEnum? _createOrNull(int? value) =>
|
||||
value == null ? null : LongEnum.fromValue(value);
|
||||
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const LongEnum LongOne = LongEnum._(2);
|
||||
static const LongEnum LongTwo = LongEnum._(4);
|
||||
static const LongEnum LongBig = LongEnum._(1099511627776);
|
||||
static const Map<int, LongEnum> values = {
|
||||
2: LongOne,
|
||||
4: LongTwo,
|
||||
1099511627776: LongBig};
|
||||
|
||||
static const fb.Reader<LongEnum> reader = _LongEnumReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LongEnum{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _LongEnumReader extends fb.Reader<LongEnum> {
|
||||
const _LongEnumReader();
|
||||
|
||||
@override
|
||||
int get size => 8;
|
||||
|
||||
@override
|
||||
LongEnum read(fb.BufferContext bc, int offset) =>
|
||||
LongEnum.fromValue(const fb.Uint64Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class AnyTypeId {
|
||||
final int value;
|
||||
const AnyTypeId._(this.value);
|
||||
@@ -114,7 +168,7 @@ class AnyTypeId {
|
||||
factory AnyTypeId.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum AnyTypeId');
|
||||
throw StateError('Invalid value $value for bit flag enum AnyTypeId');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -162,7 +216,7 @@ class AnyUniqueAliasesTypeId {
|
||||
factory AnyUniqueAliasesTypeId.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum AnyUniqueAliasesTypeId');
|
||||
throw StateError('Invalid value $value for bit flag enum AnyUniqueAliasesTypeId');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -210,7 +264,7 @@ class AnyAmbiguousAliasesTypeId {
|
||||
factory AnyAmbiguousAliasesTypeId.fromValue(int value) {
|
||||
final result = values[value];
|
||||
if (result == null) {
|
||||
throw StateError('Invalid value $value for bit flag enum AnyAmbiguousAliasesTypeId');
|
||||
throw StateError('Invalid value $value for bit flag enum AnyAmbiguousAliasesTypeId');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -264,7 +318,7 @@ class Test {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Test{a: $a, b: $b}';
|
||||
return 'Test{a: ${a}, b: ${b}}';
|
||||
}
|
||||
|
||||
TestT unpack() => TestT(
|
||||
@@ -295,7 +349,7 @@ class TestT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TestT{a: $a, b: $b}';
|
||||
return 'TestT{a: ${a}, b: ${b}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +422,7 @@ class TestSimpleTableWithEnum {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TestSimpleTableWithEnum{color: $color}';
|
||||
return 'TestSimpleTableWithEnum{color: ${color}}';
|
||||
}
|
||||
|
||||
TestSimpleTableWithEnumT unpack() => TestSimpleTableWithEnumT(
|
||||
@@ -395,7 +449,7 @@ class TestSimpleTableWithEnumT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TestSimpleTableWithEnumT{color: $color}';
|
||||
return 'TestSimpleTableWithEnumT{color: ${color}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,7 +521,7 @@ class Vec3 {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Vec3{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}';
|
||||
return 'Vec3{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}';
|
||||
}
|
||||
|
||||
Vec3T unpack() => Vec3T(
|
||||
@@ -516,7 +570,7 @@ class Vec3T implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Vec3T{x: $x, y: $y, z: $z, test1: $test1, test2: $test2, test3: $test3}';
|
||||
return 'Vec3T{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,7 +664,7 @@ class Ability {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Ability{id: $id, distance: $distance}';
|
||||
return 'Ability{id: ${id}, distance: ${distance}}';
|
||||
}
|
||||
|
||||
AbilityT unpack() => AbilityT(
|
||||
@@ -640,7 +694,7 @@ class AbilityT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AbilityT{id: $id, distance: $distance}';
|
||||
return 'AbilityT{id: ${id}, distance: ${distance}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,7 +763,7 @@ class StructOfStructs {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StructOfStructs{a: $a, b: $b, c: $c}';
|
||||
return 'StructOfStructs{a: ${a}, b: ${b}, c: ${c}}';
|
||||
}
|
||||
|
||||
StructOfStructsT unpack() => StructOfStructsT(
|
||||
@@ -743,7 +797,7 @@ class StructOfStructsT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StructOfStructsT{a: $a, b: $b, c: $c}';
|
||||
return 'StructOfStructsT{a: ${a}, b: ${b}, c: ${c}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,6 +857,94 @@ class StructOfStructsObjectBuilder extends fb.ObjectBuilder {
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class StructOfStructsOfStructs {
|
||||
StructOfStructsOfStructs._(this._bc, this._bcOffset);
|
||||
|
||||
static const fb.Reader<StructOfStructsOfStructs> reader = _StructOfStructsOfStructsReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
StructOfStructs get a => StructOfStructs.reader.read(_bc, _bcOffset + 0);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StructOfStructsOfStructs{a: ${a}}';
|
||||
}
|
||||
|
||||
StructOfStructsOfStructsT unpack() => StructOfStructsOfStructsT(
|
||||
a: a.unpack());
|
||||
|
||||
static int pack(fb.Builder fbBuilder, StructOfStructsOfStructsT? object) {
|
||||
if (object == null) return 0;
|
||||
return object.pack(fbBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
class StructOfStructsOfStructsT implements fb.Packable {
|
||||
StructOfStructsT a;
|
||||
|
||||
StructOfStructsOfStructsT({
|
||||
required this.a});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
a.pack(fbBuilder);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StructOfStructsOfStructsT{a: ${a}}';
|
||||
}
|
||||
}
|
||||
|
||||
class _StructOfStructsOfStructsReader extends fb.StructReader<StructOfStructsOfStructs> {
|
||||
const _StructOfStructsOfStructsReader();
|
||||
|
||||
@override
|
||||
int get size => 20;
|
||||
|
||||
@override
|
||||
StructOfStructsOfStructs createObject(fb.BufferContext bc, int offset) =>
|
||||
StructOfStructsOfStructs._(bc, offset);
|
||||
}
|
||||
|
||||
class StructOfStructsOfStructsBuilder {
|
||||
StructOfStructsOfStructsBuilder(this.fbBuilder);
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
int finish(fb.StructBuilder a) {
|
||||
a();
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StructOfStructsOfStructsObjectBuilder extends fb.ObjectBuilder {
|
||||
final StructOfStructsObjectBuilder _a;
|
||||
|
||||
StructOfStructsOfStructsObjectBuilder({
|
||||
required StructOfStructsObjectBuilder a,
|
||||
})
|
||||
: _a = a;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(fb.Builder fbBuilder) {
|
||||
_a.finish(fbBuilder);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String? fileIdentifier]) {
|
||||
final fbBuilder = fb.Builder(deduplicateTables: false);
|
||||
fbBuilder.finish(finish(fbBuilder), fileIdentifier);
|
||||
return fbBuilder.buffer;
|
||||
}
|
||||
}
|
||||
class Stat {
|
||||
Stat._(this._bc, this._bcOffset);
|
||||
factory Stat(List<int> bytes) {
|
||||
@@ -821,7 +963,7 @@ class Stat {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Stat{id: $id, val: $val, count: $count}';
|
||||
return 'Stat{id: ${id}, val: ${val}, count: ${count}}';
|
||||
}
|
||||
|
||||
StatT unpack() => StatT(
|
||||
@@ -858,7 +1000,7 @@ class StatT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StatT{id: $id, val: $val, count: $count}';
|
||||
return 'StatT{id: ${id}, val: ${val}, count: ${count}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,7 +1089,7 @@ class Referrable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Referrable{id: $id}';
|
||||
return 'Referrable{id: ${id}}';
|
||||
}
|
||||
|
||||
ReferrableT unpack() => ReferrableT(
|
||||
@@ -974,7 +1116,7 @@ class ReferrableT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ReferrableT{id: $id}';
|
||||
return 'ReferrableT{id: ${id}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1115,10 +1257,21 @@ class Monster {
|
||||
Race get signedEnum => Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1));
|
||||
List<int>? get testrequirednestedflatbuffer => const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 102);
|
||||
List<Stat>? get scalarKeySortedTables => const fb.ListReader<Stat>(Stat.reader).vTableGetNullable(_bc, _bcOffset, 104);
|
||||
Test? get nativeInline => Test.reader.vTableGetNullable(_bc, _bcOffset, 106);
|
||||
LongEnum get longEnumNonEnumDefault => LongEnum.fromValue(const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 108, 0));
|
||||
LongEnum get longEnumNormalDefault => LongEnum.fromValue(const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 110, 2));
|
||||
double get nanDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 112, double.nan);
|
||||
double get infDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 114, double.infinity);
|
||||
double get positiveInfDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 116, double.infinity);
|
||||
double get infinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 118, double.infinity);
|
||||
double get positiveInfinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 120, double.infinity);
|
||||
double get negativeInfDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 122, double.negativeInfinity);
|
||||
double get negativeInfinityDefault => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 124, double.negativeInfinity);
|
||||
double get doubleInfDefault => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 126, double.infinity);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables}';
|
||||
return 'Monster{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}';
|
||||
}
|
||||
|
||||
MonsterT unpack() => MonsterT(
|
||||
@@ -1171,7 +1324,18 @@ class Monster {
|
||||
vectorOfEnums: const fb.ListReader<Color>(Color.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 98),
|
||||
signedEnum: signedEnum,
|
||||
testrequirednestedflatbuffer: const fb.Uint8ListReader(lazy: false).vTableGetNullable(_bc, _bcOffset, 102),
|
||||
scalarKeySortedTables: scalarKeySortedTables?.map((e) => e.unpack()).toList());
|
||||
scalarKeySortedTables: scalarKeySortedTables?.map((e) => e.unpack()).toList(),
|
||||
nativeInline: nativeInline?.unpack(),
|
||||
longEnumNonEnumDefault: longEnumNonEnumDefault,
|
||||
longEnumNormalDefault: longEnumNormalDefault,
|
||||
nanDefault: nanDefault,
|
||||
infDefault: infDefault,
|
||||
positiveInfDefault: positiveInfDefault,
|
||||
infinityDefault: infinityDefault,
|
||||
positiveInfinityDefault: positiveInfinityDefault,
|
||||
negativeInfDefault: negativeInfDefault,
|
||||
negativeInfinityDefault: negativeInfinityDefault,
|
||||
doubleInfDefault: doubleInfDefault);
|
||||
|
||||
static int pack(fb.Builder fbBuilder, MonsterT? object) {
|
||||
if (object == null) return 0;
|
||||
@@ -1233,6 +1397,17 @@ class MonsterT implements fb.Packable {
|
||||
Race signedEnum;
|
||||
List<int>? testrequirednestedflatbuffer;
|
||||
List<StatT>? scalarKeySortedTables;
|
||||
TestT? nativeInline;
|
||||
LongEnum longEnumNonEnumDefault;
|
||||
LongEnum longEnumNormalDefault;
|
||||
double nanDefault;
|
||||
double infDefault;
|
||||
double positiveInfDefault;
|
||||
double infinityDefault;
|
||||
double positiveInfinityDefault;
|
||||
double negativeInfDefault;
|
||||
double negativeInfinityDefault;
|
||||
double doubleInfDefault;
|
||||
|
||||
MonsterT({
|
||||
this.pos,
|
||||
@@ -1284,7 +1459,18 @@ class MonsterT implements fb.Packable {
|
||||
this.vectorOfEnums,
|
||||
this.signedEnum = Race.None,
|
||||
this.testrequirednestedflatbuffer,
|
||||
this.scalarKeySortedTables});
|
||||
this.scalarKeySortedTables,
|
||||
this.nativeInline,
|
||||
this.longEnumNonEnumDefault = const LongEnum._(0),
|
||||
this.longEnumNormalDefault = LongEnum.LongOne,
|
||||
this.nanDefault = double.nan,
|
||||
this.infDefault = double.infinity,
|
||||
this.positiveInfDefault = double.infinity,
|
||||
this.infinityDefault = double.infinity,
|
||||
this.positiveInfinityDefault = double.infinity,
|
||||
this.negativeInfDefault = double.negativeInfinity,
|
||||
this.negativeInfinityDefault = double.negativeInfinity,
|
||||
this.doubleInfDefault = double.infinity});
|
||||
|
||||
@override
|
||||
int pack(fb.Builder fbBuilder) {
|
||||
@@ -1345,7 +1531,7 @@ class MonsterT implements fb.Packable {
|
||||
: fbBuilder.writeListUint8(testrequirednestedflatbuffer!);
|
||||
final int? scalarKeySortedTablesOffset = scalarKeySortedTables == null ? null
|
||||
: fbBuilder.writeList(scalarKeySortedTables!.map((b) => b.pack(fbBuilder)).toList());
|
||||
fbBuilder.startTable(50);
|
||||
fbBuilder.startTable(62);
|
||||
if (pos != null) {
|
||||
fbBuilder.addStruct(0, pos!.pack(fbBuilder));
|
||||
}
|
||||
@@ -1398,12 +1584,25 @@ class MonsterT implements fb.Packable {
|
||||
fbBuilder.addInt8(48, signedEnum.value);
|
||||
fbBuilder.addOffset(49, testrequirednestedflatbufferOffset);
|
||||
fbBuilder.addOffset(50, scalarKeySortedTablesOffset);
|
||||
if (nativeInline != null) {
|
||||
fbBuilder.addStruct(51, nativeInline!.pack(fbBuilder));
|
||||
}
|
||||
fbBuilder.addUint64(52, longEnumNonEnumDefault.value);
|
||||
fbBuilder.addUint64(53, longEnumNormalDefault.value);
|
||||
fbBuilder.addFloat32(54, nanDefault);
|
||||
fbBuilder.addFloat32(55, infDefault);
|
||||
fbBuilder.addFloat32(56, positiveInfDefault);
|
||||
fbBuilder.addFloat32(57, infinityDefault);
|
||||
fbBuilder.addFloat32(58, positiveInfinityDefault);
|
||||
fbBuilder.addFloat32(59, negativeInfDefault);
|
||||
fbBuilder.addFloat32(60, negativeInfinityDefault);
|
||||
fbBuilder.addFloat64(61, doubleInfDefault);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MonsterT{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum, testrequirednestedflatbuffer: $testrequirednestedflatbuffer, scalarKeySortedTables: $scalarKeySortedTables}';
|
||||
return 'MonsterT{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1421,7 +1620,7 @@ class MonsterBuilder {
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable(50);
|
||||
fbBuilder.startTable(62);
|
||||
}
|
||||
|
||||
int addPos(int offset) {
|
||||
@@ -1624,6 +1823,50 @@ class MonsterBuilder {
|
||||
fbBuilder.addOffset(50, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNativeInline(int offset) {
|
||||
fbBuilder.addStruct(51, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addLongEnumNonEnumDefault(LongEnum? longEnumNonEnumDefault) {
|
||||
fbBuilder.addUint64(52, longEnumNonEnumDefault?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addLongEnumNormalDefault(LongEnum? longEnumNormalDefault) {
|
||||
fbBuilder.addUint64(53, longEnumNormalDefault?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNanDefault(double? nanDefault) {
|
||||
fbBuilder.addFloat32(54, nanDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addInfDefault(double? infDefault) {
|
||||
fbBuilder.addFloat32(55, infDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addPositiveInfDefault(double? positiveInfDefault) {
|
||||
fbBuilder.addFloat32(56, positiveInfDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addInfinityDefault(double? infinityDefault) {
|
||||
fbBuilder.addFloat32(57, infinityDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addPositiveInfinityDefault(double? positiveInfinityDefault) {
|
||||
fbBuilder.addFloat32(58, positiveInfinityDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNegativeInfDefault(double? negativeInfDefault) {
|
||||
fbBuilder.addFloat32(59, negativeInfDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNegativeInfinityDefault(double? negativeInfinityDefault) {
|
||||
fbBuilder.addFloat32(60, negativeInfinityDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addDoubleInfDefault(double? doubleInfDefault) {
|
||||
fbBuilder.addFloat64(61, doubleInfDefault);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
@@ -1681,6 +1924,17 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final Race? _signedEnum;
|
||||
final List<int>? _testrequirednestedflatbuffer;
|
||||
final List<StatObjectBuilder>? _scalarKeySortedTables;
|
||||
final TestObjectBuilder? _nativeInline;
|
||||
final LongEnum? _longEnumNonEnumDefault;
|
||||
final LongEnum? _longEnumNormalDefault;
|
||||
final double? _nanDefault;
|
||||
final double? _infDefault;
|
||||
final double? _positiveInfDefault;
|
||||
final double? _infinityDefault;
|
||||
final double? _positiveInfinityDefault;
|
||||
final double? _negativeInfDefault;
|
||||
final double? _negativeInfinityDefault;
|
||||
final double? _doubleInfDefault;
|
||||
|
||||
MonsterObjectBuilder({
|
||||
Vec3ObjectBuilder? pos,
|
||||
@@ -1733,6 +1987,17 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
Race? signedEnum,
|
||||
List<int>? testrequirednestedflatbuffer,
|
||||
List<StatObjectBuilder>? scalarKeySortedTables,
|
||||
TestObjectBuilder? nativeInline,
|
||||
LongEnum? longEnumNonEnumDefault,
|
||||
LongEnum? longEnumNormalDefault,
|
||||
double? nanDefault,
|
||||
double? infDefault,
|
||||
double? positiveInfDefault,
|
||||
double? infinityDefault,
|
||||
double? positiveInfinityDefault,
|
||||
double? negativeInfDefault,
|
||||
double? negativeInfinityDefault,
|
||||
double? doubleInfDefault,
|
||||
})
|
||||
: _pos = pos,
|
||||
_mana = mana,
|
||||
@@ -1783,7 +2048,18 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
_vectorOfEnums = vectorOfEnums,
|
||||
_signedEnum = signedEnum,
|
||||
_testrequirednestedflatbuffer = testrequirednestedflatbuffer,
|
||||
_scalarKeySortedTables = scalarKeySortedTables;
|
||||
_scalarKeySortedTables = scalarKeySortedTables,
|
||||
_nativeInline = nativeInline,
|
||||
_longEnumNonEnumDefault = longEnumNonEnumDefault,
|
||||
_longEnumNormalDefault = longEnumNormalDefault,
|
||||
_nanDefault = nanDefault,
|
||||
_infDefault = infDefault,
|
||||
_positiveInfDefault = positiveInfDefault,
|
||||
_infinityDefault = infinityDefault,
|
||||
_positiveInfinityDefault = positiveInfinityDefault,
|
||||
_negativeInfDefault = negativeInfDefault,
|
||||
_negativeInfinityDefault = negativeInfinityDefault,
|
||||
_doubleInfDefault = doubleInfDefault;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
@@ -1836,7 +2112,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
: fbBuilder.writeListUint8(_testrequirednestedflatbuffer!);
|
||||
final int? scalarKeySortedTablesOffset = _scalarKeySortedTables == null ? null
|
||||
: fbBuilder.writeList(_scalarKeySortedTables!.map((b) => b.getOrCreateOffset(fbBuilder)).toList());
|
||||
fbBuilder.startTable(50);
|
||||
fbBuilder.startTable(62);
|
||||
if (_pos != null) {
|
||||
fbBuilder.addStruct(0, _pos!.finish(fbBuilder));
|
||||
}
|
||||
@@ -1889,6 +2165,19 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
fbBuilder.addInt8(48, _signedEnum?.value);
|
||||
fbBuilder.addOffset(49, testrequirednestedflatbufferOffset);
|
||||
fbBuilder.addOffset(50, scalarKeySortedTablesOffset);
|
||||
if (_nativeInline != null) {
|
||||
fbBuilder.addStruct(51, _nativeInline!.finish(fbBuilder));
|
||||
}
|
||||
fbBuilder.addUint64(52, _longEnumNonEnumDefault?.value);
|
||||
fbBuilder.addUint64(53, _longEnumNormalDefault?.value);
|
||||
fbBuilder.addFloat32(54, _nanDefault);
|
||||
fbBuilder.addFloat32(55, _infDefault);
|
||||
fbBuilder.addFloat32(56, _positiveInfDefault);
|
||||
fbBuilder.addFloat32(57, _infinityDefault);
|
||||
fbBuilder.addFloat32(58, _positiveInfinityDefault);
|
||||
fbBuilder.addFloat32(59, _negativeInfDefault);
|
||||
fbBuilder.addFloat32(60, _negativeInfinityDefault);
|
||||
fbBuilder.addFloat64(61, _doubleInfDefault);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@@ -1927,7 +2216,7 @@ class TypeAliases {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TypeAliases{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}';
|
||||
return 'TypeAliases{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}';
|
||||
}
|
||||
|
||||
TypeAliasesT unpack() => TypeAliasesT(
|
||||
@@ -2002,7 +2291,7 @@ class TypeAliasesT implements fb.Packable {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TypeAliasesT{i8: $i8, u8: $u8, i16: $i16, u16: $u16, i32: $i32, u32: $u32, i64: $i64, u64: $u64, f32: $f32, f64: $f64, v8: $v8, vf64: $vf64}';
|
||||
return 'TypeAliasesT{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
|
||||
import './include_test1_generated.dart';
|
||||
|
||||
class InParentNamespace {
|
||||
InParentNamespace._(this._bc, this._bcOffset);
|
||||
factory InParentNamespace(List<int> bytes) {
|
||||
|
||||
Binary file not shown.
@@ -82,7 +82,7 @@ pass to the `GetRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
using MyGame.Example;
|
||||
using FlatBuffers;
|
||||
using Google.FlatBuffers;
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
|
||||
|
||||
@@ -10,7 +10,7 @@ include = `include` string\_constant `;`
|
||||
|
||||
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
||||
|
||||
attribute\_decl = `attribute` ident | `"`ident`"` `;`
|
||||
attribute\_decl = `attribute` ident | `"` ident `"` `;`
|
||||
|
||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||
|
||||
@@ -31,7 +31,7 @@ type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
||||
`float32` | `float64` |
|
||||
`string` | `[` type `]` | ident
|
||||
|
||||
enumval\_decl = ident [ `=` integer\_constant ]
|
||||
enumval\_decl = ident [ `=` integer\_constant ] metadata
|
||||
|
||||
metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ To generate the docs for FlatBuffers from the source files, you
|
||||
will first need to install two programs.
|
||||
|
||||
1. You will need to install `doxygen`. See
|
||||
[Download Doxygen](http://www.stack.nl/~dimitri/doxygen/download.html).
|
||||
[Download Doxygen](https://doxygen.nl/download.html).
|
||||
|
||||
2. You will need to install `doxypypy` to format python comments appropriately.
|
||||
Install it from [here](https://github.com/Feneric/doxypypy).
|
||||
|
||||
@@ -309,11 +309,11 @@ in the corresponding C++ code. Multiple such lines per item are allowed.
|
||||
|
||||
### Attributes
|
||||
|
||||
Attributes may be attached to a declaration, behind a field, or after
|
||||
the name of a table/struct/enum/union. These may either have a value or
|
||||
not. Some attributes like `deprecated` are understood by the compiler;
|
||||
user defined ones need to be declared with the attribute declaration
|
||||
(like `priority` in the example above), and are
|
||||
Attributes may be attached to a declaration, behind a field/enum value,
|
||||
or after the name of a table/struct/enum/union. These may either have
|
||||
a value or not. Some attributes like `deprecated` are understood by
|
||||
the compiler; user defined ones need to be declared with the attribute
|
||||
declaration (like `priority` in the example above), and are
|
||||
available to query if you parse the schema at runtime.
|
||||
This is useful if you write your own code generators/editors etc., and
|
||||
you wish to add additional information specific to your tool (such as a
|
||||
@@ -552,7 +552,7 @@ the world. If this is not practical for you, use explicit field ids, which
|
||||
should always generate a merge conflict if two people try to allocate the same
|
||||
id.
|
||||
|
||||
### Schema evolution examples
|
||||
### Schema evolution examples (tables)
|
||||
|
||||
Some examples to clarify what happens as you change a schema:
|
||||
|
||||
@@ -614,6 +614,41 @@ Occasionally ok. You've renamed fields, which will break all code (and JSON
|
||||
files!) that use this schema, but as long as the change is obvious, this is not
|
||||
incompatible with the actual binary buffers, since those only ever address
|
||||
fields by id/offset.
|
||||
|
||||
#### Schema evolution examples (unions)
|
||||
|
||||
Suppose we have the following schema:
|
||||
```
|
||||
union Foo { A, B }
|
||||
```
|
||||
We can add another variant at the end.
|
||||
```
|
||||
union Foo { A, B, another_a: A }
|
||||
```
|
||||
and this will be okay. Old code will not recognize `another_a`.
|
||||
However if we add `another_a` anywhere but the end, e.g.
|
||||
```
|
||||
union Foo { A, another_a: A, B }
|
||||
```
|
||||
this is not okay. When new code writes `another_a`, old code will
|
||||
misinterpret it as `B` (and vice versa). However you can explicitly
|
||||
set the union's "discriminant" value like so:
|
||||
```
|
||||
union Foo { A = 1, another_a: A = 3, B = 2 }
|
||||
```
|
||||
This is okay.
|
||||
|
||||
```
|
||||
union Foo { original_a: A = 1, another_a: A = 3, B = 2 }
|
||||
```
|
||||
Renaming fields will break code and any saved human readable representations,
|
||||
such as json files, but the binary buffers will be the same.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
### Testing whether a field is present in a table
|
||||
|
||||
@@ -415,7 +415,7 @@ The first step is to import/include the library, generated files, etc.
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
using FlatBuffers;
|
||||
using Google.FlatBuffers;
|
||||
using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.)
|
||||
~~~
|
||||
</div>
|
||||
@@ -2200,7 +2200,7 @@ before:
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
using FlatBuffers;
|
||||
using Google.FlatBuffers;
|
||||
using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.)
|
||||
~~~
|
||||
</div>
|
||||
@@ -3449,7 +3449,7 @@ Java supports vectors of unions, but it isn't currently documented.
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
using FlatBuffers;
|
||||
using Google.FlatBuffers;
|
||||
using Example.VectorOfUnions;
|
||||
|
||||
var fbb = new FlatBufferBuilder(100);
|
||||
|
||||
27
examples/go-echo/README.md
Normal file
27
examples/go-echo/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Go Echo Example
|
||||
|
||||
A simple example demonstrating how to send flatbuffers over the network in Go.
|
||||
|
||||
## Generate flatbuffer code
|
||||
|
||||
```
|
||||
flatc -g --gen-object-api --go-module-name echo hero.fbs net.fbs
|
||||
```
|
||||
|
||||
## Running example
|
||||
|
||||
1. Run go mod tidy to get dependencies
|
||||
```
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
2. Start a server
|
||||
```
|
||||
go run server/server.go
|
||||
```
|
||||
|
||||
3. Run the client in another terminal
|
||||
```
|
||||
go run client/client.go
|
||||
```
|
||||
|
||||
51
examples/go-echo/client/client.go
Normal file
51
examples/go-echo/client/client.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"echo/hero"
|
||||
"echo/net"
|
||||
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
func RequestBody() *bytes.Reader {
|
||||
b := flatbuffers.NewBuilder(0)
|
||||
r := net.RequestT{Player: &hero.WarriorT{Name: "Krull", Hp: 100}}
|
||||
b.Finish(r.Pack(b))
|
||||
return bytes.NewReader(b.FinishedBytes())
|
||||
}
|
||||
|
||||
func ReadResponse(r *http.Response) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read request body: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
res := net.GetRootAsResponse(body, 0)
|
||||
player := res.Player(nil)
|
||||
|
||||
fmt.Printf("Got response (name: %v, hp: %v)\n", string(player.Name()), player.Hp())
|
||||
}
|
||||
|
||||
func main() {
|
||||
body := RequestBody()
|
||||
req, err := http.NewRequest("POST", "http://localhost:8080/echo", body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
client := http.DefaultClient
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
ReadResponse(resp)
|
||||
}
|
||||
5
examples/go-echo/go.mod
Normal file
5
examples/go-echo/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module echo
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/google/flatbuffers v22.10.26+incompatible
|
||||
6
examples/go-echo/hero.fbs
Normal file
6
examples/go-echo/hero.fbs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace hero;
|
||||
|
||||
table Warrior {
|
||||
name: string;
|
||||
hp: uint32;
|
||||
}
|
||||
93
examples/go-echo/hero/Warrior.go
Normal file
93
examples/go-echo/hero/Warrior.go
Normal file
@@ -0,0 +1,93 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package hero
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type WarriorT struct {
|
||||
Name string `json:"name"`
|
||||
Hp uint32 `json:"hp"`
|
||||
}
|
||||
|
||||
func (t *WarriorT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
if t == nil { return 0 }
|
||||
nameOffset := builder.CreateString(t.Name)
|
||||
WarriorStart(builder)
|
||||
WarriorAddName(builder, nameOffset)
|
||||
WarriorAddHp(builder, t.Hp)
|
||||
return WarriorEnd(builder)
|
||||
}
|
||||
|
||||
func (rcv *Warrior) UnPackTo(t *WarriorT) {
|
||||
t.Name = string(rcv.Name())
|
||||
t.Hp = rcv.Hp()
|
||||
}
|
||||
|
||||
func (rcv *Warrior) UnPack() *WarriorT {
|
||||
if rcv == nil { return nil }
|
||||
t := &WarriorT{}
|
||||
rcv.UnPackTo(t)
|
||||
return t
|
||||
}
|
||||
|
||||
type Warrior struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &Warrior{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &Warrior{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func (rcv *Warrior) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *Warrior) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *Warrior) Name() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *Warrior) Hp() uint32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetUint32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *Warrior) MutateHp(n uint32) bool {
|
||||
return rcv._tab.MutateUint32Slot(6, n)
|
||||
}
|
||||
|
||||
func WarriorStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(2)
|
||||
}
|
||||
func WarriorAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
|
||||
}
|
||||
func WarriorAddHp(builder *flatbuffers.Builder, hp uint32) {
|
||||
builder.PrependUint32Slot(1, hp, 0)
|
||||
}
|
||||
func WarriorEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
11
examples/go-echo/net.fbs
Normal file
11
examples/go-echo/net.fbs
Normal file
@@ -0,0 +1,11 @@
|
||||
include "hero.fbs";
|
||||
|
||||
namespace net;
|
||||
|
||||
table Request {
|
||||
player: hero.Warrior;
|
||||
}
|
||||
|
||||
table Response {
|
||||
player: hero.Warrior;
|
||||
}
|
||||
82
examples/go-echo/net/Request.go
Normal file
82
examples/go-echo/net/Request.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
|
||||
hero "echo/hero"
|
||||
)
|
||||
|
||||
type RequestT struct {
|
||||
Player *hero.WarriorT `json:"player"`
|
||||
}
|
||||
|
||||
func (t *RequestT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
if t == nil { return 0 }
|
||||
playerOffset := t.Player.Pack(builder)
|
||||
RequestStart(builder)
|
||||
RequestAddPlayer(builder, playerOffset)
|
||||
return RequestEnd(builder)
|
||||
}
|
||||
|
||||
func (rcv *Request) UnPackTo(t *RequestT) {
|
||||
t.Player = rcv.Player(nil).UnPack()
|
||||
}
|
||||
|
||||
func (rcv *Request) UnPack() *RequestT {
|
||||
if rcv == nil { return nil }
|
||||
t := &RequestT{}
|
||||
rcv.UnPackTo(t)
|
||||
return t
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &Request{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &Request{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func (rcv *Request) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *Request) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *Request) Player(obj *hero.Warrior) *hero.Warrior {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(hero.Warrior)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func RequestAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0)
|
||||
}
|
||||
func RequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
82
examples/go-echo/net/Response.go
Normal file
82
examples/go-echo/net/Response.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
|
||||
hero "echo/hero"
|
||||
)
|
||||
|
||||
type ResponseT struct {
|
||||
Player *hero.WarriorT `json:"player"`
|
||||
}
|
||||
|
||||
func (t *ResponseT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
if t == nil { return 0 }
|
||||
playerOffset := t.Player.Pack(builder)
|
||||
ResponseStart(builder)
|
||||
ResponseAddPlayer(builder, playerOffset)
|
||||
return ResponseEnd(builder)
|
||||
}
|
||||
|
||||
func (rcv *Response) UnPackTo(t *ResponseT) {
|
||||
t.Player = rcv.Player(nil).UnPack()
|
||||
}
|
||||
|
||||
func (rcv *Response) UnPack() *ResponseT {
|
||||
if rcv == nil { return nil }
|
||||
t := &ResponseT{}
|
||||
rcv.UnPackTo(t)
|
||||
return t
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &Response{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &Response{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func (rcv *Response) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *Response) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *Response) Player(obj *hero.Warrior) *hero.Warrior {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(hero.Warrior)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func ResponseAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0)
|
||||
}
|
||||
func ResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
29
examples/go-echo/server/server.go
Normal file
29
examples/go-echo/server/server.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"echo/net"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func echo(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read request body: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
req := net.GetRootAsRequest(body, 0)
|
||||
player := req.Player(nil)
|
||||
|
||||
fmt.Printf("Got request (name: %v, hp: %v)\n", string(player.Name()), player.Hp())
|
||||
w.Write(body)
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/echo", echo)
|
||||
|
||||
fmt.Println("Listening on port :8080")
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package flatbuffers
|
||||
|
||||
import "sort"
|
||||
|
||||
// Builder is a state machine for creating FlatBuffer objects.
|
||||
// Use a Builder to construct object(s) starting from leaf nodes.
|
||||
//
|
||||
@@ -315,6 +317,25 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
|
||||
return b.Offset()
|
||||
}
|
||||
|
||||
// CreateVectorOfTables serializes slice of table offsets into a vector.
|
||||
func (b *Builder) CreateVectorOfTables(offsets []UOffsetT) UOffsetT {
|
||||
b.assertNotNested()
|
||||
b.StartVector(4, len(offsets), 4)
|
||||
for i := len(offsets) - 1; i >= 0; i-- {
|
||||
b.PrependUOffsetT(offsets[i])
|
||||
}
|
||||
return b.EndVector(len(offsets))
|
||||
}
|
||||
|
||||
type KeyCompare func(o1, o2 UOffsetT, buf []byte) bool
|
||||
|
||||
func (b *Builder) CreateVectorOfSortedTables(offsets []UOffsetT, keyCompare KeyCompare) UOffsetT {
|
||||
sort.Slice(offsets, func(i, j int) bool {
|
||||
return keyCompare(offsets[i], offsets[j], b.Bytes)
|
||||
})
|
||||
return b.CreateVectorOfTables(offsets)
|
||||
}
|
||||
|
||||
// CreateSharedString Checks if the string is already written
|
||||
// to the buffer before calling CreateString
|
||||
func (b *Builder) CreateSharedString(s string) UOffsetT {
|
||||
|
||||
@@ -23,3 +23,8 @@ func GetSizePrefixedRootAs(buf []byte, offset UOffsetT, fb FlatBuffer) {
|
||||
func GetSizePrefix(buf []byte, offset UOffsetT) uint32 {
|
||||
return GetUint32(buf[offset:])
|
||||
}
|
||||
|
||||
// GetIndirectOffset retrives the relative offset in the provided buffer stored at `offset`.
|
||||
func GetIndirectOffset(buf []byte, offset UOffsetT) UOffsetT {
|
||||
return offset + GetUOffsetT(buf[offset:])
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import FlatBuffers
|
||||
|
||||
public struct models_HelloReply: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
@@ -55,7 +55,7 @@ extension models_HelloReply: Encodable {
|
||||
|
||||
public struct models_HelloRequest: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ template<typename T, uint16_t length> class Array {
|
||||
public:
|
||||
typedef uint16_t size_type;
|
||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
||||
typedef VectorIterator<T, return_type> const_iterator;
|
||||
typedef VectorConstIterator<T, return_type> const_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__)
|
||||
#include <utility.h>
|
||||
#else
|
||||
#include <utility>
|
||||
@@ -139,8 +139,8 @@
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 22
|
||||
#define FLATBUFFERS_VERSION_MINOR 9
|
||||
#define FLATBUFFERS_VERSION_REVISION 24
|
||||
#define FLATBUFFERS_VERSION_MINOR 12
|
||||
#define FLATBUFFERS_VERSION_REVISION 06
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef FLATBUFFERS_BUFFER_H_
|
||||
#define FLATBUFFERS_BUFFER_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
@@ -76,6 +78,9 @@ template<typename T> struct IndirectHelper {
|
||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
|
||||
}
|
||||
static return_type Read(uint8_t *p, uoffset_t i) {
|
||||
return Read(const_cast<const uint8_t *>(p), i);
|
||||
}
|
||||
};
|
||||
template<typename T> struct IndirectHelper<Offset<T>> {
|
||||
typedef const T *return_type;
|
||||
@@ -85,13 +90,20 @@ template<typename T> struct IndirectHelper<Offset<T>> {
|
||||
p += i * sizeof(uoffset_t);
|
||||
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
|
||||
}
|
||||
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
|
||||
p += i * sizeof(uoffset_t);
|
||||
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p));
|
||||
}
|
||||
};
|
||||
template<typename T> struct IndirectHelper<const T *> {
|
||||
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));
|
||||
return reinterpret_cast<return_type>(p + i * sizeof(T));
|
||||
}
|
||||
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
|
||||
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,4 +151,4 @@ template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_BUFFER_H_
|
||||
#endif // FLATBUFFERS_BUFFER_H_
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_
|
||||
#define FLATBUFFERS_FLATBUFFER_BUILDER_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef FLATBUFFERS_H_
|
||||
#define FLATBUFFERS_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// TODO: These includes are for mitigating the pains of users editing their
|
||||
// source because they relied on flatbuffers.h to include everything for them.
|
||||
#include "flatbuffers/array.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FLATBUFFERS_FLEXBUFFERS_H_
|
||||
#define FLATBUFFERS_FLEXBUFFERS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
// Used to select STL variant.
|
||||
#include "flatbuffers/base.h"
|
||||
@@ -382,9 +383,10 @@ class Reference {
|
||||
type_(type) {}
|
||||
|
||||
Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
|
||||
: data_(data), parent_width_(parent_width) {
|
||||
byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3);
|
||||
type_ = static_cast<Type>(packed_type >> 2);
|
||||
: data_(data),
|
||||
parent_width_(parent_width),
|
||||
byte_width_(1 << (packed_type & 3)),
|
||||
type_(static_cast<Type>(packed_type >> 2)) {
|
||||
}
|
||||
|
||||
Type GetType() const { return type_; }
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef FLATBUFFERS_IDL_H_
|
||||
#define FLATBUFFERS_IDL_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -382,7 +383,14 @@ struct EnumVal {
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
||||
bool Deserialize(Parser &parser, const reflection::EnumVal *val);
|
||||
|
||||
flatbuffers::Offset<
|
||||
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool DeserializeAttributes(Parser &parser,
|
||||
const Vector<Offset<reflection::KeyValue>> *attrs);
|
||||
|
||||
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
|
||||
int64_t GetAsInt64() const { return value; }
|
||||
@@ -392,6 +400,7 @@ struct EnumVal {
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
Type union_type;
|
||||
SymbolTable<Value> attributes;
|
||||
|
||||
private:
|
||||
friend EnumDef;
|
||||
@@ -464,6 +473,10 @@ inline bool IsStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||
}
|
||||
|
||||
inline bool IsIncompleteStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->predecl;
|
||||
}
|
||||
|
||||
inline bool IsTable(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
|
||||
}
|
||||
@@ -480,11 +493,11 @@ inline bool IsVector(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_VECTOR;
|
||||
}
|
||||
|
||||
inline bool IsVectorOfStruct(const Type& type) {
|
||||
inline bool IsVectorOfStruct(const Type &type) {
|
||||
return IsVector(type) && IsStruct(type.VectorType());
|
||||
}
|
||||
|
||||
inline bool IsVectorOfTable(const Type& type) {
|
||||
inline bool IsVectorOfTable(const Type &type) {
|
||||
return IsVector(type) && IsTable(type.VectorType());
|
||||
}
|
||||
|
||||
@@ -528,8 +541,11 @@ inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
|
||||
inline bool EqualByName(const Type &a, const Type &b) {
|
||||
return a.base_type == b.base_type && a.element == b.element &&
|
||||
(a.struct_def == b.struct_def ||
|
||||
a.struct_def->name == b.struct_def->name) &&
|
||||
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
|
||||
(a.struct_def != nullptr && b.struct_def != nullptr &&
|
||||
a.struct_def->name == b.struct_def->name)) &&
|
||||
(a.enum_def == b.enum_def ||
|
||||
(a.enum_def != nullptr && b.enum_def != nullptr &&
|
||||
a.enum_def->name == b.enum_def->name));
|
||||
}
|
||||
|
||||
struct RPCCall : public Definition {
|
||||
@@ -578,6 +594,7 @@ struct IDLOptions {
|
||||
bool strict_json;
|
||||
bool output_default_scalars_in_json;
|
||||
int indent_step;
|
||||
bool cpp_minify_enums;
|
||||
bool output_enum_identifiers;
|
||||
bool prefixed_enums;
|
||||
bool scoped_enums;
|
||||
@@ -613,6 +630,7 @@ struct IDLOptions {
|
||||
bool binary_schema_gen_embed;
|
||||
std::string go_import;
|
||||
std::string go_namespace;
|
||||
std::string go_module_name;
|
||||
bool protobuf_ascii_alike;
|
||||
bool size_prefixed;
|
||||
std::string root_type;
|
||||
@@ -634,6 +652,7 @@ struct IDLOptions {
|
||||
bool json_nested_legacy_flatbuffers;
|
||||
bool ts_flat_file;
|
||||
bool no_leak_private_annotations;
|
||||
bool require_json_eof;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language {
|
||||
@@ -653,6 +672,7 @@ struct IDLOptions {
|
||||
kRust = 1 << 14,
|
||||
kKotlin = 1 << 15,
|
||||
kSwift = 1 << 16,
|
||||
kNim = 1 << 17,
|
||||
kMAX
|
||||
};
|
||||
|
||||
@@ -687,6 +707,7 @@ struct IDLOptions {
|
||||
strict_json(false),
|
||||
output_default_scalars_in_json(false),
|
||||
indent_step(2),
|
||||
cpp_minify_enums(false),
|
||||
output_enum_identifiers(true),
|
||||
prefixed_enums(true),
|
||||
scoped_enums(false),
|
||||
@@ -734,6 +755,7 @@ struct IDLOptions {
|
||||
json_nested_legacy_flatbuffers(false),
|
||||
ts_flat_file(false),
|
||||
no_leak_private_annotations(false),
|
||||
require_json_eof(true),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
require_explicit_ids(false),
|
||||
rust_serialize(false),
|
||||
@@ -746,7 +768,8 @@ struct IDLOptions {
|
||||
// This encapsulates where the parser is in the current source file.
|
||||
struct ParserState {
|
||||
ParserState()
|
||||
: cursor_(nullptr),
|
||||
: prev_cursor_(nullptr),
|
||||
cursor_(nullptr),
|
||||
line_start_(nullptr),
|
||||
line_(0),
|
||||
token_(-1),
|
||||
@@ -754,6 +777,7 @@ struct ParserState {
|
||||
|
||||
protected:
|
||||
void ResetState(const char *source) {
|
||||
prev_cursor_ = source;
|
||||
cursor_ = source;
|
||||
line_ = 0;
|
||||
MarkNewLine();
|
||||
@@ -768,7 +792,8 @@ struct ParserState {
|
||||
FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
|
||||
return static_cast<int64_t>(cursor_ - line_start_);
|
||||
}
|
||||
|
||||
|
||||
const char *prev_cursor_;
|
||||
const char *cursor_;
|
||||
const char *line_start_;
|
||||
int line_; // the current line being parsed
|
||||
@@ -896,6 +921,9 @@ class Parser : public ParserState {
|
||||
|
||||
bool ParseJson(const char *json, const char *json_filename = nullptr);
|
||||
|
||||
// Returns the number of characters were consumed when parsing a JSON string.
|
||||
std::ptrdiff_t BytesConsumed() const;
|
||||
|
||||
// Set the root type. May override the one set in the schema.
|
||||
bool SetRootType(const char *name);
|
||||
|
||||
@@ -1016,6 +1044,7 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
||||
bool isextend, bool inside_oneof);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
|
||||
|
||||
@@ -407,8 +407,9 @@ struct ToStringVisitor : public IterationVisitor {
|
||||
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||
const TypeTable *type_table,
|
||||
bool multi_line = false,
|
||||
bool vector_delimited = true) {
|
||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
|
||||
bool vector_delimited = true,
|
||||
const std::string& indent = "") {
|
||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, indent,
|
||||
vector_delimited);
|
||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||
return tostring_visitor.s;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 9 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 24,
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 6,
|
||||
"Non-compatible flatbuffers version included");
|
||||
|
||||
namespace reflection {
|
||||
@@ -265,7 +265,7 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *key() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_KEY);
|
||||
}
|
||||
bool KeyCompareLessThan(const KeyValue *o) const {
|
||||
bool KeyCompareLessThan(const KeyValue * const o) const {
|
||||
return *key() < *o->key();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_key) const {
|
||||
@@ -334,7 +334,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_NAME = 4,
|
||||
VT_VALUE = 6,
|
||||
VT_UNION_TYPE = 10,
|
||||
VT_DOCUMENTATION = 12
|
||||
VT_DOCUMENTATION = 12,
|
||||
VT_ATTRIBUTES = 14
|
||||
};
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
@@ -342,7 +343,7 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int64_t value() const {
|
||||
return GetField<int64_t>(VT_VALUE, 0);
|
||||
}
|
||||
bool KeyCompareLessThan(const EnumVal *o) const {
|
||||
bool KeyCompareLessThan(const EnumVal * const o) const {
|
||||
return value() < o->value();
|
||||
}
|
||||
int KeyCompareWithValue(int64_t _value) const {
|
||||
@@ -354,6 +355,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
@@ -364,6 +368,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.VerifyVector(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||
verifier.VerifyVector(attributes()) &&
|
||||
verifier.VerifyVectorOfTables(attributes()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@@ -384,6 +391,9 @@ struct EnumValBuilder {
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(EnumVal::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
@@ -401,9 +411,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0) {
|
||||
EnumValBuilder builder_(_fbb);
|
||||
builder_.add_value(value);
|
||||
builder_.add_attributes(attributes);
|
||||
builder_.add_documentation(documentation);
|
||||
builder_.add_union_type(union_type);
|
||||
builder_.add_name(name);
|
||||
@@ -415,15 +427,18 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
const char *name = nullptr,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
return reflection::CreateEnumVal(
|
||||
_fbb,
|
||||
name__,
|
||||
value,
|
||||
union_type,
|
||||
documentation__);
|
||||
documentation__,
|
||||
attributes__);
|
||||
}
|
||||
|
||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -440,7 +455,7 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Enum *o) const {
|
||||
bool KeyCompareLessThan(const Enum * const o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_name) const {
|
||||
@@ -591,7 +606,7 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Field *o) const {
|
||||
bool KeyCompareLessThan(const Field * const o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_name) const {
|
||||
@@ -797,7 +812,7 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Object *o) const {
|
||||
bool KeyCompareLessThan(const Object * const o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_name) const {
|
||||
@@ -949,7 +964,7 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const RPCCall *o) const {
|
||||
bool KeyCompareLessThan(const RPCCall * const o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_name) const {
|
||||
@@ -1065,7 +1080,7 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Service *o) const {
|
||||
bool KeyCompareLessThan(const Service * const o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_name) const {
|
||||
@@ -1184,7 +1199,7 @@ struct SchemaFile FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *filename() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILENAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const SchemaFile *o) const {
|
||||
bool KeyCompareLessThan(const SchemaFile * const o) const {
|
||||
return *filename() < *o->filename();
|
||||
}
|
||||
int KeyCompareWithValue(const char *_filename) const {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <stdio.h>
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace flatbuffers {
|
||||
@@ -392,6 +393,18 @@ inline uint64_t StringToUInt(const char *s, int base = 10) {
|
||||
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
||||
}
|
||||
|
||||
inline bool StringIsFlatbufferNan(const std::string &s) {
|
||||
return s == "nan" || s == "+nan" || s == "-nan";
|
||||
}
|
||||
|
||||
inline bool StringIsFlatbufferPositiveInfinity(const std::string &s) {
|
||||
return s == "inf" || s == "+inf" || s == "infinity" || s == "+infinity";
|
||||
}
|
||||
|
||||
inline bool StringIsFlatbufferNegativeInfinity(const std::string &s) {
|
||||
return s == "-inf" || s == "-infinity";
|
||||
}
|
||||
|
||||
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
||||
std::string *dest);
|
||||
typedef bool (*FileExistsFunction)(const char *filename);
|
||||
|
||||
@@ -27,14 +27,15 @@ struct String;
|
||||
|
||||
// An STL compatible iterator implementation for Vector below, effectively
|
||||
// calling Get() for every element.
|
||||
template<typename T, typename IT> struct VectorIterator {
|
||||
template<typename T, typename IT, typename Data = uint8_t *>
|
||||
struct VectorIterator {
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef IT value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef IT *pointer;
|
||||
typedef IT &reference;
|
||||
|
||||
VectorIterator(const uint8_t *data, uoffset_t i)
|
||||
VectorIterator(Data data, uoffset_t i)
|
||||
: data_(data + IndirectHelper<T>::element_stride * i) {}
|
||||
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
|
||||
VectorIterator() : data_(nullptr) {}
|
||||
@@ -116,9 +117,12 @@ template<typename T, typename IT> struct VectorIterator {
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t *data_;
|
||||
Data data_;
|
||||
};
|
||||
|
||||
template<typename T, typename IT>
|
||||
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>;
|
||||
|
||||
template<typename Iterator>
|
||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||
explicit VectorReverseIterator(Iterator iter)
|
||||
@@ -145,7 +149,7 @@ template<typename T> class Vector {
|
||||
public:
|
||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
||||
iterator;
|
||||
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
|
||||
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type>
|
||||
const_iterator;
|
||||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
|
||||
#define FLATBUFFERS_VECTOR_DOWNWARD_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/default_allocator.h"
|
||||
#include "flatbuffers/detached_buffer.h"
|
||||
|
||||
35
java/pom.xml
35
java/pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-java</artifactId>
|
||||
<version>22.9.24</version>
|
||||
<version>22.12.06</version>
|
||||
<packaging>bundle</packaging>
|
||||
<name>FlatBuffers Java API</name>
|
||||
<description>
|
||||
@@ -58,19 +58,17 @@
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<release>8</release>
|
||||
<testExcludes>
|
||||
<testExclude>**/LongEnum.java</testExclude>
|
||||
<testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude>
|
||||
<testExclude>MyGame/Example/StructOfStructs**</testExclude>
|
||||
<testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude>
|
||||
</testExcludes>
|
||||
</configuration>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<release>8</release>
|
||||
<testExcludes>
|
||||
<testExclude>MyGame/Example/MonsterStorageGrpc.java</testExclude>
|
||||
<testExclude>MyGame/OtherNameSpace/TableBT.java</testExclude>
|
||||
</testExcludes>
|
||||
</configuration>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
@@ -149,10 +147,10 @@
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<gpgArguments>
|
||||
<arg>--pinentry-mode</arg>
|
||||
<arg>loopback</arg>
|
||||
</gpgArguments>
|
||||
<gpgArguments>
|
||||
<arg>--pinentry-mode</arg>
|
||||
<arg>loopback</arg>
|
||||
</gpgArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -173,4 +171,3 @@
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class Constants {
|
||||
Changes to the Java implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_22_9_24() {}
|
||||
public static void FLATBUFFERS_22_12_06() {}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
@@ -32,6 +32,6 @@ namespace Google.FlatBuffers
|
||||
Changes to the C# implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_22_9_24() {}
|
||||
public static void FLATBUFFERS_22_12_06() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.1;netstandard2.0;net46</TargetFrameworks>
|
||||
<Description>A cross-platform memory efficient serialization library</Description>
|
||||
<PackageVersion>22.9.24</PackageVersion>
|
||||
<PackageVersion>22.12.06</PackageVersion>
|
||||
<Authors>Google LLC</Authors>
|
||||
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>
|
||||
|
||||
7
nim/flatbuffers.nimble
Normal file
7
nim/flatbuffers.nimble
Normal file
@@ -0,0 +1,7 @@
|
||||
version = "2.0.8"
|
||||
author = "flatbuffers"
|
||||
description = "Flatbuffers"
|
||||
license = "Apache 2.0"
|
||||
srcDir = "flatbuffers"
|
||||
|
||||
requires "nim >= 1.4.0"
|
||||
7
nim/flatbuffers/flatbuffers.nim
Normal file
7
nim/flatbuffers/flatbuffers.nim
Normal file
@@ -0,0 +1,7 @@
|
||||
import
|
||||
src/[
|
||||
builder,
|
||||
struct,
|
||||
table
|
||||
]
|
||||
export flatbuffers.builder, flatbuffers.table, flatbuffers.struct
|
||||
262
nim/flatbuffers/src/builder.nim
Normal file
262
nim/flatbuffers/src/builder.nim
Normal file
@@ -0,0 +1,262 @@
|
||||
import math
|
||||
import table
|
||||
|
||||
|
||||
const MAX_BUFFER_SIZE* = 2^31
|
||||
|
||||
|
||||
type Builder* = ref object of RootObj
|
||||
bytes*: seq[byte]
|
||||
minalign*: int
|
||||
current_vtable*: seq[uoffset]
|
||||
objectEnd*: uoffset
|
||||
vtables*: seq[uoffset] #?
|
||||
head*: uoffset
|
||||
nested*: bool
|
||||
finished*: bool
|
||||
vectorNumElems*: uoffset
|
||||
|
||||
using this: var Builder
|
||||
|
||||
func newBuilder*(size: int): Builder =
|
||||
result = new Builder
|
||||
result.bytes.setLen(size)
|
||||
result.minalign = 1
|
||||
result.head = size.uoffset
|
||||
result.nested = false
|
||||
result.finished = false
|
||||
result.vectorNumElems = 0
|
||||
|
||||
proc FinishedBytes*(this): seq[byte] =
|
||||
if not this.finished:
|
||||
quit("Builder not finished, Incorrect use of FinishedBytes(): must call 'Finish' first.")
|
||||
result = this.bytes[this.head..^1]
|
||||
|
||||
proc Output*(this): seq[byte] =
|
||||
if not this.finished:
|
||||
quit("Builder not finished, Incorrect use of Output(): must call 'Finish' first.")
|
||||
|
||||
result = this.bytes[this.head..^1]
|
||||
|
||||
func Offset*(this): uoffset =
|
||||
result = this.bytes.len.uoffset - this.head
|
||||
|
||||
proc StartObject*(this; numfields: int) =
|
||||
if this.nested:
|
||||
quit("builder is nested")
|
||||
|
||||
this.current_vtable.setLen(numfields)
|
||||
for i in this.current_vtable.mitems():
|
||||
i = 0
|
||||
this.objectEnd = this.Offset()
|
||||
this.nested = true
|
||||
|
||||
proc GrowByteBuffer*(this) =
|
||||
if this.bytes.len == MAX_BUFFER_SIZE:
|
||||
quit("flatbuffers: cannot grow buffer beyond 2 gigabytes")
|
||||
let oldLen = this.bytes.len
|
||||
var newLen = min(this.bytes.len * 2, MAX_BUFFER_SIZE)
|
||||
if newLen == 0:
|
||||
newLen = 1
|
||||
this.bytes.setLen(newLen)
|
||||
var j = this.bytes.len - 1
|
||||
while j >= 0:
|
||||
if j >= newLen - oldLen:
|
||||
this.bytes[j] = this.bytes[j - (newLen - oldLen)]
|
||||
else:
|
||||
this.bytes[j] = 0
|
||||
dec(j)
|
||||
|
||||
proc Place*[T](this; x: T) =
|
||||
this.head -= uoffset x.sizeof
|
||||
WriteVal(this.bytes, this.head, x)
|
||||
|
||||
func Pad*(this; n: int) =
|
||||
for i in 0..<n:
|
||||
this.Place(0.byte)
|
||||
|
||||
proc Prep*(this; size: int; additionalBytes: int) =
|
||||
if size > this.minalign:
|
||||
this.minalign = size
|
||||
var alignsize = (not (this.bytes.len - this.head.int + additionalBytes)) + 1
|
||||
alignsize = alignsize and (size - 1)
|
||||
|
||||
while this.head.int < alignsize + size + additionalBytes:
|
||||
let oldbufSize = this.bytes.len
|
||||
this.GrowByteBuffer()
|
||||
this.head = (this.head.int + this.bytes.len - oldbufSize).uoffset
|
||||
this.Pad(alignsize)
|
||||
|
||||
proc PrependOffsetRelative*[T: Offsets](this; off: T) =
|
||||
when T is voffset:
|
||||
this.Prep(T.sizeof, 0)
|
||||
if not off.uoffset <= this.Offset:
|
||||
quit("flatbuffers: Offset arithmetic error.")
|
||||
this.Place(off)
|
||||
else:
|
||||
this.Prep(T.sizeof, 0)
|
||||
if not off.uoffset <= this.Offset:
|
||||
quit("flatbuffers: Offset arithmetic error.")
|
||||
let off2: T = this.Offset.T - off + sizeof(T).T
|
||||
this.Place(off2)
|
||||
|
||||
|
||||
proc Prepend*[T](this; x: T) =
|
||||
this.Prep(x.sizeof, 0)
|
||||
this.Place(x)
|
||||
|
||||
proc Slot*(this; slotnum: int) =
|
||||
this.current_vtable[slotnum] = this.Offset
|
||||
|
||||
proc PrependSlot*[T](this; o: int; x, d: T) =
|
||||
if x != d:
|
||||
when T is uoffset or T is soffset or T is voffset:
|
||||
this.PrependOffsetRelative(x)
|
||||
else:
|
||||
this.Prepend(x)
|
||||
this.Slot(o)
|
||||
|
||||
proc AssertStuctInline(this; obj: uoffset) =
|
||||
if obj != this.Offset:
|
||||
quit("flatbuffers: Tried to write a Struct at an Offset that is different from the current Offset of the Builder.")
|
||||
|
||||
proc PrependStructSlot*(this; o: int; x: uoffset; d: uoffset) =
|
||||
if x != d:
|
||||
this.AssertStuctInline(x)
|
||||
this.Slot(o)
|
||||
|
||||
proc Add*[T](this; n: T) =
|
||||
this.Prep(T.sizeof, 0)
|
||||
WriteVal(this.bytes, this.head, n)
|
||||
|
||||
proc VtableEqual*(a: seq[uoffset]; objectStart: uoffset; b: seq[byte]): bool =
|
||||
if a.len * voffset.sizeof != b.len:
|
||||
return false
|
||||
|
||||
var i = 0
|
||||
while i < a.len:
|
||||
var seq = b[i * voffset.sizeof..<(i + 1) * voffset.sizeof]
|
||||
let x = GetVal[voffset](addr seq)
|
||||
|
||||
if x == 0 and a[i] == 0:
|
||||
inc i
|
||||
continue
|
||||
|
||||
let y = objectStart.soffset - a[i].soffset
|
||||
if x.soffset != y:
|
||||
return false
|
||||
inc i
|
||||
return true
|
||||
|
||||
proc WriteVtable*(this): uoffset =
|
||||
this.PrependOffsetRelative(0.soffset)
|
||||
|
||||
let objectOffset = this.Offset
|
||||
var existingVtable = uoffset 0
|
||||
|
||||
var i = this.current_vtable.len - 1
|
||||
while i >= 0 and this.current_vtable[i] == 0: dec i
|
||||
|
||||
this.current_vtable = this.current_vtable[0..i]
|
||||
for i in countdown(this.vtables.len - 1, 0):
|
||||
let
|
||||
vt2Offset: uoffset = this.vtables[i]
|
||||
vt2Start: int = this.bytes.len - int vt2Offset
|
||||
|
||||
var seq = this.bytes[vt2Start..<this.bytes.len]
|
||||
let
|
||||
vt2Len = GetVal[voffset](addr seq)
|
||||
metadata = 2 * voffset.sizeof # VtableMetadataFields * SizeVOffsetT
|
||||
vt2End = vt2Start + vt2Len.int
|
||||
vt2 = this.bytes[this.bytes.len - vt2Offset.int + metadata..<vt2End]
|
||||
|
||||
if VtableEqual(this.current_vtable, objectOffset, vt2):
|
||||
existingVtable = vt2Offset
|
||||
break
|
||||
|
||||
if existingVtable == 0:
|
||||
for i in countdown(this.current_vtable.len - 1, 0):
|
||||
var off: uoffset
|
||||
if this.current_vtable[i] != 0:
|
||||
off = objectOffset - this.current_vtable[i]
|
||||
|
||||
this.PrependOffsetRelative(off.voffset)
|
||||
|
||||
let objectSize = objectOffset - this.objectEnd
|
||||
this.PrependOffsetRelative(objectSize.voffset)
|
||||
|
||||
let vBytes = (this.current_vtable.len + 2) * voffset.sizeof
|
||||
this.PrependOffsetRelative(vBytes.voffset)
|
||||
|
||||
let objectStart: uoffset = (this.bytes.len.uoffset - objectOffset)
|
||||
WriteVal(this.bytes, objectStart, (this.Offset - objectOffset).soffset)
|
||||
this.vtables.add this.Offset
|
||||
else:
|
||||
let objectStart: uoffset = this.bytes.len.uoffset - objectOffset
|
||||
this.head = objectStart
|
||||
WriteVal(this.bytes, this.head,
|
||||
(existingVtable.soffset - objectOffset.soffset))
|
||||
|
||||
this.current_vtable = @[]
|
||||
result = objectOffset
|
||||
|
||||
proc EndObject*(this): uoffset =
|
||||
if not this.nested:
|
||||
quit("builder is not nested")
|
||||
result = this.WriteVtable()
|
||||
this.nested = false
|
||||
|
||||
proc End*(this: var Builder): uoffset =
|
||||
result = this.EndObject()
|
||||
|
||||
proc StartVector*(this; elemSize: int; numElems: uoffset;
|
||||
alignment: int) =
|
||||
if this.nested:
|
||||
quit("builder is nested")
|
||||
this.nested = true
|
||||
this.vectorNumElems = numElems
|
||||
this.Prep(sizeof(uint32), elemSize * numElems.int)
|
||||
this.Prep(alignment, elemSize * numElems.int)
|
||||
|
||||
proc EndVector*(this): uoffset =
|
||||
if not this.nested:
|
||||
quit("builder is not nested")
|
||||
this.nested = false
|
||||
this.Place(this.vectorNumElems)
|
||||
this.vectorNumElems = 0
|
||||
result = this.Offset
|
||||
|
||||
proc getChars*(str: seq[byte]): string =
|
||||
var bytes = str
|
||||
result = GetVal[string](addr bytes)
|
||||
|
||||
proc getBytes*(str: string | cstring): seq[byte] =
|
||||
for chr in str:
|
||||
result.add byte chr
|
||||
result.add byte 0
|
||||
|
||||
proc Create*[T](this; s: T): uoffset = # Both CreateString and CreateByteVector functionality
|
||||
if this.nested:
|
||||
quit("builder is nested")
|
||||
this.nested = true
|
||||
when T is cstring or T is string:
|
||||
let x = s.getBytes()
|
||||
let l = x.len.uoffset
|
||||
this.vectorNumElems = l-1
|
||||
else:
|
||||
let x = s
|
||||
let l = x.len.uoffset
|
||||
this.vectorNumElems = l
|
||||
this.Prep(uoffset.sizeof, l.int * byte.sizeof)
|
||||
this.head -= l
|
||||
this.bytes[this.head..<this.head+l] = x
|
||||
result = this.EndVector()
|
||||
|
||||
proc Finish*(this; rootTable: uoffset) =
|
||||
if this.nested:
|
||||
quit("builder is nested")
|
||||
this.nested = true
|
||||
|
||||
this.Prep(this.minalign, uoffset.sizeof)
|
||||
this.PrependOffsetRelative(rootTable)
|
||||
this.finished = true
|
||||
12
nim/flatbuffers/src/endian.nim
Normal file
12
nim/flatbuffers/src/endian.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
template swapEndian*(outp, inp: pointer, size: int) =
|
||||
var i = cast[cstring](inp)
|
||||
var o = cast[cstring](outp)
|
||||
for x in 0..<size:
|
||||
o[x] = i[(0..<size).len - x - 1]
|
||||
|
||||
when system.cpuEndian == bigEndian:
|
||||
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)
|
||||
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
|
||||
else:
|
||||
func littleEndianX*(outp, inp: pointer, size: int) {.inline.} = copyMem(outp, inp, size)
|
||||
func bigEndianX*(outp, inp: pointer, size: int) {.inline.} = swapEndian(outp, inp, size)
|
||||
24
nim/flatbuffers/src/struct.nim
Normal file
24
nim/flatbuffers/src/struct.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
import table
|
||||
|
||||
|
||||
type FlatObj* {.inheritable.} = object
|
||||
tab*: Vtable
|
||||
|
||||
func Table*(this: var FlatObj): Vtable = this.tab
|
||||
|
||||
func Init*(this: var FlatObj; buf: seq[byte]; i: uoffset) =
|
||||
this.tab.Bytes = buf
|
||||
this.tab.Pos = i
|
||||
|
||||
# Cant define it in table.nim since it needs FlatObj and Init
|
||||
func GetUnion*[T: FlatObj](this: var Vtable; off: uoffset): T =
|
||||
result.Init(this.Bytes, this.Indirect(off))
|
||||
|
||||
func GetRootAs*(result: var FlatObj; buf: seq[byte]; offset: uoffset) =
|
||||
var
|
||||
vtable = Vtable(Bytes: buf[offset..^1], Pos: offset)
|
||||
n = Get[uoffset](vtable, offset)
|
||||
result.Init(buf, n+offset)
|
||||
|
||||
func GetRootAs*(result: var FlatObj; buf: string; offset: uoffset) =
|
||||
result.GetRootAs(cast[seq[byte]](buf), offset)
|
||||
149
nim/flatbuffers/src/table.nim
Normal file
149
nim/flatbuffers/src/table.nim
Normal file
@@ -0,0 +1,149 @@
|
||||
import endian
|
||||
|
||||
|
||||
type
|
||||
uoffset* = uint32 ## offset in to the buffer
|
||||
soffset* = int32 ## offset from start of table, to a vtable
|
||||
voffset* = uint16 ## offset from start of table to value
|
||||
|
||||
type Offsets* = uoffset | soffset | voffset
|
||||
|
||||
type Vtable* = object
|
||||
Bytes*: seq[byte]
|
||||
Pos*: uoffset
|
||||
|
||||
|
||||
using this: Vtable
|
||||
|
||||
|
||||
func GetVal*[T](b: ptr seq[byte]): T {.inline.} =
|
||||
when T is float64:
|
||||
result = cast[T](GetVal[uint64](b))
|
||||
elif T is float32:
|
||||
result = cast[T](GetVal[uint32](b))
|
||||
elif T is string:
|
||||
result = cast[T](b[])
|
||||
else:
|
||||
if b[].len < T.sizeof:
|
||||
b[].setLen T.sizeof
|
||||
result = cast[ptr T](unsafeAddr b[][0])[]
|
||||
|
||||
|
||||
template Get*[T](this; off: uoffset): T =
|
||||
var seq = this.Bytes[off..^1]
|
||||
GetVal[T](addr seq)
|
||||
|
||||
template Get*[T](this; off: soffset): T =
|
||||
var seq = this.Bytes[off..^1]
|
||||
GetVal[T](addr seq)
|
||||
|
||||
template Get*[T](this; off: voffset): T =
|
||||
var seq = this.Bytes[off..^1]
|
||||
GetVal[T](addr seq)
|
||||
|
||||
func WriteVal*[T: not SomeFloat](b: var openArray[byte]; off: uoffset;
|
||||
n: T) {.inline.} =
|
||||
when sizeof(T) == 8:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 4:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 2:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 1:
|
||||
b[off] = n.uint8
|
||||
else:
|
||||
discard
|
||||
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
#{.error:"shouldnt appear".}
|
||||
|
||||
func WriteVal*[T: not SomeFloat](b: var seq[byte]; off: uoffset;
|
||||
n: T) {.inline.} =
|
||||
when sizeof(T) == 8:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 4:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 2:
|
||||
littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
elif sizeof(T) == 1:
|
||||
b[off] = n.uint8
|
||||
else:
|
||||
discard
|
||||
#littleEndianX(addr b[off], unsafeAddr n, T.sizeof)
|
||||
#{.error:"shouldnt appear".}
|
||||
|
||||
func WriteVal*[T: SomeFloat](b: var openArray[byte]; off: uoffset;
|
||||
n: T) {.inline.} =
|
||||
when T is float64:
|
||||
WriteVal(b, off, cast[uint64](n))
|
||||
elif T is float32:
|
||||
WriteVal(b, off, cast[uint32](n))
|
||||
|
||||
func WriteVal*[T: SomeFloat](b: var seq[byte]; off: uoffset; n: T) {.inline.} =
|
||||
when T is float64:
|
||||
WriteVal(b, off, cast[uint64](n))
|
||||
elif T is float32:
|
||||
WriteVal(b, off, cast[uint32](n))
|
||||
|
||||
func Offset*(this; off: voffset): voffset =
|
||||
let vtable = (this.Pos - this.Get[:uoffset](this.Pos)).voffset
|
||||
let vtableEnd = this.Get[:voffset](vtable)
|
||||
if off < vtableEnd:
|
||||
return this.Get[:voffset](vtable + off)
|
||||
return 0
|
||||
|
||||
|
||||
func Indirect*(this; off: uoffset): uoffset =
|
||||
result = off + this.Get[:uoffset](off)
|
||||
|
||||
func VectorLen*(this; off: uoffset): int =
|
||||
var newoff: uoffset = off + this.Pos
|
||||
newoff += this.Get[:uoffset](newoff)
|
||||
return this.Get[:uoffset](newoff).int
|
||||
|
||||
func Vector*(this; off: uoffset): uoffset =
|
||||
let newoff: uoffset = off + this.Pos
|
||||
var x: uoffset = newoff + this.Get[:uoffset](newoff)
|
||||
x += (uoffset.sizeof).uoffset
|
||||
result = x
|
||||
|
||||
func Union*(this; off: uoffset): Vtable =
|
||||
let newoff: uoffset = off + this.Pos
|
||||
result.Pos = newoff + this.Get[:uoffset](newoff)
|
||||
result.Bytes = this.Bytes
|
||||
|
||||
func GetSlot*[T](this; slot: voffset; d: T): T =
|
||||
let off = this.Offset(slot)
|
||||
if off == 0:
|
||||
return d
|
||||
return this.Get[T](this.Pos + off)
|
||||
|
||||
func GetOffsetSlot*[T: Offsets](this; slot: voffset; d: T): T =
|
||||
let off = this.Offset(slot)
|
||||
if off == 0:
|
||||
return d
|
||||
return off
|
||||
|
||||
func ByteVector*(this; off: uoffset): seq[byte] =
|
||||
let
|
||||
newoff: uoffset = off + this.Get[:uoffset](off)
|
||||
start = newoff + (uoffset.sizeof).uoffset
|
||||
var newseq = this.Bytes[newoff..^1]
|
||||
let
|
||||
length = GetVal[uoffset](addr newseq)
|
||||
result = this.Bytes[start..<start+length]
|
||||
|
||||
func String*(this; off: uoffset): string =
|
||||
var byte_seq = this.ByteVector(off)
|
||||
result = GetVal[string](addr byte_seq)
|
||||
|
||||
using this: var Vtable
|
||||
|
||||
proc Mutate*[T](this; off: uoffset; n: T): bool =
|
||||
WriteVal(this.Bytes, off, n)
|
||||
return true
|
||||
|
||||
func MutateSlot*[T](this; slot: voffset; n: T): bool =
|
||||
let off: voffset = this.Offset(slot)
|
||||
if off != 0:
|
||||
return this.Mutate(this.Pos + off.uoffset, n)
|
||||
return false
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flatbuffers",
|
||||
"version": "22.9.24",
|
||||
"version": "22.12.06",
|
||||
"description": "Memory Efficient Serialization Library",
|
||||
"files": [
|
||||
"js/**/*.js",
|
||||
@@ -17,6 +17,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run compile && cd tests/ts && python3 ./TypeScriptTest.py",
|
||||
"lint": "eslint ts",
|
||||
"compile": "tsc && tsc -p tsconfig.mjs.json && rollup -c",
|
||||
"prepublishOnly": "npm install --only=dev && npm run compile"
|
||||
},
|
||||
|
||||
@@ -486,7 +486,12 @@ class ByteBuffer
|
||||
}
|
||||
|
||||
private static function validateValue($min, $max, $value, $type, $additional_notes = "") {
|
||||
if(!($min <= $value && $value <= $max)) {
|
||||
if (
|
||||
!(
|
||||
($type === "byte" && $min <= ord($value) && ord($value) <= $max) ||
|
||||
($min <= $value && $value <= $max)
|
||||
)
|
||||
) {
|
||||
throw new \InvalidArgumentException(sprintf("bad number %s for type %s.%s", $value, $type, $additional_notes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
|
||||
# Placeholder, to be updated during the release process
|
||||
# by the setup.py
|
||||
__version__ = u"22.9.24"
|
||||
__version__ = u"22.12.06"
|
||||
|
||||
@@ -112,7 +112,8 @@ class Builder(object):
|
||||
|
||||
## @cond FLATBUFFERS_INTENRAL
|
||||
__slots__ = ("Bytes", "current_vtable", "head", "minalign", "objectEnd",
|
||||
"vtables", "nested", "forceDefaults", "finished", "vectorNumElems")
|
||||
"vtables", "nested", "forceDefaults", "finished", "vectorNumElems",
|
||||
"sharedStrings")
|
||||
|
||||
"""Maximum buffer size constant, in bytes.
|
||||
|
||||
@@ -141,6 +142,7 @@ class Builder(object):
|
||||
self.vtables = {}
|
||||
self.nested = False
|
||||
self.forceDefaults = False
|
||||
self.sharedStrings = {}
|
||||
## @endcond
|
||||
self.finished = False
|
||||
|
||||
@@ -405,6 +407,20 @@ class Builder(object):
|
||||
self.vectorNumElems = None
|
||||
return self.Offset()
|
||||
|
||||
def CreateSharedString(self, s, encoding='utf-8', errors='strict'):
|
||||
"""
|
||||
CreateSharedString checks if the string is already written to the buffer
|
||||
before calling CreateString.
|
||||
"""
|
||||
|
||||
if s in self.sharedStrings:
|
||||
return self.sharedStrings[s]
|
||||
|
||||
off = self.CreateString(s, encoding, errors)
|
||||
self.sharedStrings[s] = off
|
||||
|
||||
return off
|
||||
|
||||
def CreateString(self, s, encoding='utf-8', errors='strict'):
|
||||
"""CreateString writes a null-terminated byte string as a vector."""
|
||||
|
||||
|
||||
@@ -73,7 +73,32 @@ class EnumVal(object):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
|
||||
return o == 0
|
||||
|
||||
def EnumValStart(builder): builder.StartObject(5)
|
||||
# EnumVal
|
||||
def Attributes(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||
if o != 0:
|
||||
x = self._tab.Vector(o)
|
||||
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
|
||||
x = self._tab.Indirect(x)
|
||||
from reflection.KeyValue import KeyValue
|
||||
obj = KeyValue()
|
||||
obj.Init(self._tab.Bytes, x)
|
||||
return obj
|
||||
return None
|
||||
|
||||
# EnumVal
|
||||
def AttributesLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# EnumVal
|
||||
def AttributesIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
|
||||
return o == 0
|
||||
|
||||
def EnumValStart(builder): builder.StartObject(6)
|
||||
def Start(builder):
|
||||
return EnumValStart(builder)
|
||||
def EnumValAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
|
||||
@@ -91,6 +116,12 @@ def AddDocumentation(builder, documentation):
|
||||
def EnumValStartDocumentationVector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
||||
def StartDocumentationVector(builder, numElems):
|
||||
return EnumValStartDocumentationVector(builder, numElems)
|
||||
def EnumValAddAttributes(builder, attributes): builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
|
||||
def AddAttributes(builder, attributes):
|
||||
return EnumValAddAttributes(builder, attributes)
|
||||
def EnumValStartAttributesVector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
||||
def StartAttributesVector(builder, numElems):
|
||||
return EnumValStartAttributesVector(builder, numElems)
|
||||
def EnumValEnd(builder): return builder.EndObject()
|
||||
def End(builder):
|
||||
return EnumValEnd(builder)
|
||||
@@ -1,2 +1,6 @@
|
||||
[bdist_wheel]
|
||||
universal=1
|
||||
|
||||
[metadata]
|
||||
license_files =
|
||||
../license.txt
|
||||
@@ -12,54 +12,15 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import fileinput
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
def _update_version_attr(new_version):
|
||||
for line in fileinput.input('flatbuffers/_version.py', inplace=True):
|
||||
if line.startswith('__version__'):
|
||||
line = re.sub(r'".*"', '"{}"'.format(new_version), line)
|
||||
sys.stdout.write(line)
|
||||
|
||||
|
||||
def version():
|
||||
version = os.getenv('VERSION', None)
|
||||
if version:
|
||||
# Most git tags are prefixed with 'v' (example: v1.2.3) this is
|
||||
# never desirable for artifact repositories, so we strip the
|
||||
# leading 'v' if it's present.
|
||||
version = version[1:] if version.startswith('v') else version
|
||||
else:
|
||||
# Default version is an ISO8601 compiliant datetime. PyPI doesn't allow
|
||||
# the colon ':' character in its versions, and time is required to allow
|
||||
# for multiple publications to master in one day. This datetime string
|
||||
# uses the "basic" ISO8601 format for both its date and time components
|
||||
# to avoid issues with the colon character (ISO requires that date and
|
||||
# time components of a date-time string must be uniformly basic or
|
||||
# extended, which is why the date component does not have dashes.
|
||||
#
|
||||
# Publications using datetime versions should only be made from master
|
||||
# to represent the HEAD moving forward.
|
||||
version = datetime.utcnow().strftime('%Y%m%d%H%M%S')
|
||||
print("VERSION environment variable not set, using datetime instead: {}"
|
||||
.format(version))
|
||||
|
||||
_update_version_attr(version)
|
||||
|
||||
return version
|
||||
|
||||
|
||||
setup(
|
||||
name='flatbuffers',
|
||||
version=version(),
|
||||
version='22.12.06',
|
||||
license='Apache 2.0',
|
||||
author='FlatBuffers Contributors',
|
||||
author_email='me@rwinslow.com',
|
||||
license_files='../LICENSE.txt',
|
||||
author='Derek Bailey',
|
||||
author_email='derekbailey@google.com',
|
||||
url='https://google.github.io/flatbuffers/',
|
||||
long_description=('Python runtime library for use with the '
|
||||
'`Flatbuffers <https://google.github.io/flatbuffers/>`_ '
|
||||
@@ -81,4 +42,4 @@ setup(
|
||||
'Documentation': 'https://google.github.io/flatbuffers/',
|
||||
'Source': 'https://github.com/google/flatbuffers',
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
10
readme.md
10
readme.md
@@ -2,6 +2,7 @@
|
||||
===========
|
||||
|
||||

|
||||
[](https://buildkite.com/bazel/flatbuffers)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:flatbuffers)
|
||||
[](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers)
|
||||
[](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
@@ -17,7 +18,7 @@ maximum memory efficiency. It allows you to directly access serialized data with
|
||||
|
||||
## Supported operating systems
|
||||
* Windows
|
||||
* MacOS X
|
||||
* macOS
|
||||
* Linux
|
||||
* Android
|
||||
* And any others with a recent C++ compiler (C++ 11 and newer)
|
||||
@@ -39,12 +40,9 @@ Code generation and runtime libraries for many popular languages.
|
||||
1. PHP
|
||||
1. Python - [PyPi](https://pypi.org/project/flatbuffers/)
|
||||
1. Rust - [crates.io](https://crates.io/crates/flatbuffers)
|
||||
1. Swift
|
||||
1. Swift - [swiftpackageindex](https://swiftpackageindex.com/google/flatbuffers)
|
||||
1. TypeScript - [NPM](https://www.npmjs.com/package/flatbuffers)
|
||||
|
||||
*and more in progress...*
|
||||
|
||||
1. [Nim](https://github.com/google/flatbuffers/pull/7362)
|
||||
1. Nim
|
||||
|
||||
## Contribution
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ table EnumVal {
|
||||
object:Object (deprecated);
|
||||
union_type:Type;
|
||||
documentation:[string];
|
||||
attributes:[KeyValue];
|
||||
}
|
||||
|
||||
table Enum {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flatbuffers"
|
||||
version = "2.1.2"
|
||||
version = "22.12.6"
|
||||
edition = "2018"
|
||||
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
|
||||
license = "Apache-2.0"
|
||||
@@ -12,15 +12,13 @@ categories = ["encoding", "data-structures", "memory-management"]
|
||||
rust = "1.51"
|
||||
|
||||
[features]
|
||||
default = ["thiserror"]
|
||||
no_std = ["core2", "thiserror_core2"]
|
||||
default = ["std"]
|
||||
std = []
|
||||
serialize = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
smallvec = "1.6.1"
|
||||
bitflags = "1.2.1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
thiserror = { version = "1.0.30", optional = true }
|
||||
core2 = { version = "0.4.0", optional = true }
|
||||
# This version is compliant with mainline 1.0.30
|
||||
thiserror_core2 = { version = "2.0.0", default-features = false, optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.4.0"
|
||||
|
||||
12
rust/flatbuffers/build.rs
Normal file
12
rust/flatbuffers/build.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use rustc_version::{version_meta, Channel};
|
||||
|
||||
fn main() {
|
||||
let version_meta = version_meta().unwrap();
|
||||
|
||||
// To use nightly features we declare this and then we can use
|
||||
// #[cfg(nightly)]
|
||||
// for nightly only features
|
||||
if version_meta.channel == Channel::Nightly {
|
||||
println!("cargo:rustc-cfg=nightly")
|
||||
}
|
||||
}
|
||||
@@ -37,14 +37,18 @@ where
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
#[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
|
||||
impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
|
||||
/// # Safety
|
||||
///
|
||||
/// buf must be a contiguous array of `T`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `buf.len()` is not `size_of::<T>() * N`
|
||||
#[inline(always)]
|
||||
pub fn new(buf: &'a [u8]) -> Self {
|
||||
assert!(size_of::<T>() * N == buf.len());
|
||||
pub unsafe fn new(buf: &'a [u8]) -> Self {
|
||||
assert_eq!(size_of::<T>() * N, buf.len());
|
||||
|
||||
Array {
|
||||
0: buf,
|
||||
1: PhantomData,
|
||||
}
|
||||
Array(buf, PhantomData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -61,34 +65,39 @@ impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
|
||||
pub fn get(&self, idx: usize) -> T::Inner {
|
||||
assert!(idx < N);
|
||||
let sz = size_of::<T>();
|
||||
T::follow(self.0, sz * idx)
|
||||
// Safety:
|
||||
// self.0 was valid for length `N` on construction and have verified `idx < N`
|
||||
unsafe { T::follow(self.0, sz * idx) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter(&self) -> VectorIter<'a, T> {
|
||||
VectorIter::from_slice(self.0, self.len())
|
||||
// Safety:
|
||||
// self.0 was valid for length N on construction
|
||||
unsafe { VectorIter::from_slice(self.0, self.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Follow<'a> + Debug, const N: usize> Into<[T::Inner; N]> for Array<'a, T, N> {
|
||||
#[inline(always)]
|
||||
fn into(self) -> [T::Inner; N] {
|
||||
array_init(|i| self.get(i))
|
||||
impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
|
||||
fn from(array: Array<'a, T, N>) -> Self {
|
||||
array_init(|i| array.get(i))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(caspern): Implement some future safe version of SafeSliceAccess.
|
||||
|
||||
/// Implement Follow for all possible Arrays that have Follow-able elements.
|
||||
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
|
||||
type Inner = Array<'a, T, N>;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Array::new(&buf[loc..loc + N * size_of::<T>()])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
||||
/// Place an array of EndianScalar into the provided mutable byte slice. Performs
|
||||
/// endian conversion, if necessary.
|
||||
/// # Safety
|
||||
/// Caller must ensure `s.len() >= size_of::<[T; N]>()`
|
||||
pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
||||
buf: &mut [u8],
|
||||
loc: usize,
|
||||
src: &[T; N],
|
||||
@@ -96,14 +105,12 @@ pub fn emplace_scalar_array<T: EndianScalar, const N: usize>(
|
||||
let mut buf_ptr = buf[loc..].as_mut_ptr();
|
||||
for item in src.iter() {
|
||||
let item_le = item.to_little_endian();
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(
|
||||
&item_le as *const T as *const u8,
|
||||
buf_ptr,
|
||||
size_of::<T>(),
|
||||
);
|
||||
buf_ptr = buf_ptr.add(size_of::<T>());
|
||||
}
|
||||
core::ptr::copy_nonoverlapping(
|
||||
&item_le as *const T::Scalar as *const u8,
|
||||
buf_ptr,
|
||||
size_of::<T::Scalar>(),
|
||||
);
|
||||
buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +131,8 @@ where
|
||||
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
|
||||
let mut ptr_i = array.as_mut_ptr() as *mut T;
|
||||
|
||||
// Safety:
|
||||
// array is aligned by T, and has length N
|
||||
unsafe {
|
||||
for i in 0..N {
|
||||
let value_i = initializer(i);
|
||||
@@ -134,7 +143,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="serialize")]
|
||||
#[cfg(feature = "serialize")]
|
||||
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
|
||||
where
|
||||
T: 'a + Follow<'a>,
|
||||
|
||||
@@ -14,26 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
extern crate smallvec;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{vec, vec::Vec};
|
||||
use core::cmp::max;
|
||||
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr::write_bytes;
|
||||
use core::slice::from_raw_parts;
|
||||
#[cfg(feature = "no_std")]
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
use crate::endian_scalar::{emplace_scalar, read_scalar_at};
|
||||
use crate::endian_scalar::emplace_scalar;
|
||||
use crate::primitives::*;
|
||||
use crate::push::{Push, PushAlignment};
|
||||
use crate::read_scalar;
|
||||
use crate::table::Table;
|
||||
use crate::vector::{SafeSliceAccess, Vector};
|
||||
use crate::vector::Vector;
|
||||
use crate::vtable::{field_index_to_field_offset, VTable};
|
||||
use crate::vtable_writer::VTableWriter;
|
||||
|
||||
pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
struct FieldLoc {
|
||||
off: UOffsetT,
|
||||
@@ -120,7 +116,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
// memset only the part of the buffer that could be dirty:
|
||||
{
|
||||
let to_clear = self.owned_buf.len() - self.head;
|
||||
let ptr = (&mut self.owned_buf[self.head..]).as_mut_ptr();
|
||||
let ptr = self.owned_buf[self.head..].as_mut_ptr();
|
||||
// Safety:
|
||||
// Verified ptr is valid for `to_clear` above
|
||||
unsafe {
|
||||
write_bytes(ptr, 0, to_clear);
|
||||
}
|
||||
@@ -152,8 +150,10 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
self.align(sz, P::alignment());
|
||||
self.make_space(sz);
|
||||
{
|
||||
let (dst, rest) = (&mut self.owned_buf[self.head..]).split_at_mut(sz);
|
||||
x.push(dst, rest);
|
||||
let (dst, rest) = self.owned_buf[self.head..].split_at_mut(sz);
|
||||
// Safety:
|
||||
// Called make_space above
|
||||
unsafe { x.push(dst, rest.len()) };
|
||||
}
|
||||
WIPOffset::new(self.used_space() as UOffsetT)
|
||||
}
|
||||
@@ -309,73 +309,32 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
WIPOffset::new(self.used_space() as UOffsetT)
|
||||
}
|
||||
|
||||
/// Create a vector by memcpy'ing. This is much faster than calling
|
||||
/// `create_vector`, but the underlying type must be represented as
|
||||
/// little-endian on the host machine. This property is encoded in the
|
||||
/// type system through the SafeSliceAccess trait. The following types are
|
||||
/// always safe, on any platform: bool, u8, i8, and any
|
||||
/// FlatBuffers-generated struct.
|
||||
#[inline]
|
||||
pub fn create_vector_direct<'a: 'b, 'b, T: SafeSliceAccess + Push + Sized + 'b>(
|
||||
&'a mut self,
|
||||
items: &'b [T],
|
||||
) -> WIPOffset<Vector<'fbb, T>> {
|
||||
self.assert_not_nested(
|
||||
"create_vector_direct can not be called when a table or vector is under construction",
|
||||
);
|
||||
let elem_size = T::size();
|
||||
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||
|
||||
let bytes = {
|
||||
let ptr = items.as_ptr() as *const T as *const u8;
|
||||
unsafe { from_raw_parts(ptr, items.len() * elem_size) }
|
||||
};
|
||||
self.push_bytes_unprefixed(bytes);
|
||||
self.push(items.len() as UOffsetT);
|
||||
|
||||
WIPOffset::new(self.used_space() as UOffsetT)
|
||||
}
|
||||
|
||||
/// Create a vector of strings.
|
||||
///
|
||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
||||
#[inline]
|
||||
pub fn create_vector_of_strings<'a, 'b>(
|
||||
&'a mut self,
|
||||
xs: &'b [&'b str],
|
||||
) -> WIPOffset<Vector<'fbb, ForwardsUOffset<&'fbb str>>> {
|
||||
self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction");
|
||||
// internally, smallvec can be a stack-allocated or heap-allocated vector:
|
||||
// if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap.
|
||||
let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> =
|
||||
smallvec::SmallVec::with_capacity(xs.len());
|
||||
unsafe {
|
||||
offsets.set_len(xs.len());
|
||||
}
|
||||
|
||||
// note that this happens in reverse, because the buffer is built back-to-front:
|
||||
for (i, &s) in xs.iter().enumerate().rev() {
|
||||
let o = self.create_string(s);
|
||||
offsets[i] = o;
|
||||
}
|
||||
self.create_vector(&offsets[..])
|
||||
}
|
||||
|
||||
/// Create a vector of Push-able objects.
|
||||
///
|
||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
||||
#[inline]
|
||||
pub fn create_vector<'a: 'b, 'b, T: Push + Copy + 'b>(
|
||||
pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
|
||||
&'a mut self,
|
||||
items: &'b [T],
|
||||
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
||||
let elem_size = T::size();
|
||||
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||
for i in (0..items.len()).rev() {
|
||||
self.push(items[i]);
|
||||
let slice_size = items.len() * elem_size;
|
||||
self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||
self.ensure_capacity(slice_size + UOffsetT::size());
|
||||
|
||||
self.head -= slice_size;
|
||||
let mut written_len = self.owned_buf.len() - self.head;
|
||||
|
||||
let buf = &mut self.owned_buf[self.head..self.head + slice_size];
|
||||
for (item, out) in items.iter().zip(buf.chunks_exact_mut(elem_size)) {
|
||||
written_len -= elem_size;
|
||||
|
||||
// Safety:
|
||||
// Called ensure_capacity and aligned to T above
|
||||
unsafe { item.push(out, written_len) };
|
||||
}
|
||||
|
||||
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
|
||||
}
|
||||
|
||||
@@ -384,17 +343,18 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
/// Speed-sensitive users may wish to reduce memory usage by creating the
|
||||
/// vector manually: use `start_vector`, `push`, and `end_vector`.
|
||||
#[inline]
|
||||
pub fn create_vector_from_iter<T: Push + Copy>(
|
||||
pub fn create_vector_from_iter<T: Push>(
|
||||
&mut self,
|
||||
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
|
||||
) -> WIPOffset<Vector<'fbb, T::Output>> {
|
||||
let elem_size = T::size();
|
||||
let len = items.len();
|
||||
self.align(len * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
|
||||
let mut actual = 0;
|
||||
for item in items.rev() {
|
||||
self.push(item);
|
||||
actual += 1;
|
||||
}
|
||||
WIPOffset::new(self.push::<UOffsetT>(len as UOffsetT).value())
|
||||
WIPOffset::new(self.push::<UOffsetT>(actual).value())
|
||||
}
|
||||
|
||||
/// Set whether default values are stored.
|
||||
@@ -443,7 +403,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
assert_msg_name: &'static str,
|
||||
) {
|
||||
let idx = self.used_space() - tab_revloc.value() as usize;
|
||||
let tab = Table::new(&self.owned_buf[self.head..], idx);
|
||||
|
||||
// Safety:
|
||||
// The value of TableFinishedWIPOffset is the offset from the end of owned_buf
|
||||
// to an SOffsetT pointing to a valid VTable
|
||||
//
|
||||
// `self.owned_buf.len() = self.used_space() + self.head`
|
||||
// `self.owned_buf.len() - tab_revloc = self.used_space() - tab_revloc + self.head`
|
||||
// `self.owned_buf.len() - tab_revloc = idx + self.head`
|
||||
let tab = unsafe { Table::new(&self.owned_buf[self.head..], idx) };
|
||||
let o = tab.vtable().get(slot_byte_loc) as usize;
|
||||
assert!(o != 0, "missing required field {}", assert_msg_name);
|
||||
}
|
||||
@@ -560,11 +528,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
}
|
||||
}
|
||||
let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos];
|
||||
let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| {
|
||||
let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize;
|
||||
let old_vtable = VTable::init(&self.owned_buf, old_vtable_pos);
|
||||
new_vt_bytes.cmp(old_vtable.as_bytes())
|
||||
});
|
||||
let found = self
|
||||
.written_vtable_revpos
|
||||
.binary_search_by(|old_vtable_revpos: &UOffsetT| {
|
||||
let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize;
|
||||
// Safety:
|
||||
// Already written vtables are valid by construction
|
||||
let old_vtable = unsafe { VTable::init(&self.owned_buf, old_vtable_pos) };
|
||||
new_vt_bytes.cmp(old_vtable.as_bytes())
|
||||
});
|
||||
let final_vtable_revpos = match found {
|
||||
Ok(i) => {
|
||||
// The new vtable is a duplicate so clear it.
|
||||
@@ -581,12 +553,22 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
};
|
||||
// Write signed offset from table to its vtable.
|
||||
let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize;
|
||||
let tmp_soffset_to_vt = unsafe { read_scalar_at::<UOffsetT>(&self.owned_buf, table_pos) };
|
||||
debug_assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
|
||||
if cfg!(debug_assertions) {
|
||||
// Safety:
|
||||
// Verified slice length
|
||||
let tmp_soffset_to_vt = unsafe {
|
||||
read_scalar::<UOffsetT>(&self.owned_buf[table_pos..table_pos + SIZE_UOFFSET])
|
||||
};
|
||||
assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
|
||||
}
|
||||
|
||||
let buf = &mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET];
|
||||
// Safety:
|
||||
// Verified length of buf above
|
||||
unsafe {
|
||||
emplace_scalar::<SOffsetT>(
|
||||
&mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET],
|
||||
final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT
|
||||
buf,
|
||||
final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -623,7 +605,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
|
||||
}
|
||||
// finally, zero out the old end data.
|
||||
{
|
||||
let ptr = (&mut self.owned_buf[..middle]).as_mut_ptr();
|
||||
let ptr = self.owned_buf[..middle].as_mut_ptr();
|
||||
// Safety:
|
||||
// ptr is byte aligned and of length middle
|
||||
unsafe {
|
||||
write_bytes(ptr, 0, middle);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,24 @@
|
||||
|
||||
use core::mem::size_of;
|
||||
|
||||
mod private {
|
||||
/// Types that are trivially transmutable are those where any combination of bits
|
||||
/// represents a valid value of that type
|
||||
///
|
||||
/// For example integral types are TriviallyTransmutable as all bit patterns are valid,
|
||||
/// however, `bool` is not trivially transmutable as only `0` and `1` are valid
|
||||
pub trait TriviallyTransmutable {}
|
||||
|
||||
impl TriviallyTransmutable for i8 {}
|
||||
impl TriviallyTransmutable for i16 {}
|
||||
impl TriviallyTransmutable for i32 {}
|
||||
impl TriviallyTransmutable for i64 {}
|
||||
impl TriviallyTransmutable for u8 {}
|
||||
impl TriviallyTransmutable for u16 {}
|
||||
impl TriviallyTransmutable for u32 {}
|
||||
impl TriviallyTransmutable for u64 {}
|
||||
}
|
||||
|
||||
/// Trait for values that must be stored in little-endian byte order, but
|
||||
/// might be represented in memory as big-endian. Every type that implements
|
||||
/// EndianScalar is a valid FlatBuffers scalar value.
|
||||
@@ -28,144 +46,118 @@ use core::mem::size_of;
|
||||
/// "too much". For example, num-traits provides i128 support, but that is an
|
||||
/// invalid FlatBuffers type.
|
||||
pub trait EndianScalar: Sized + PartialEq + Copy + Clone {
|
||||
fn to_little_endian(self) -> Self;
|
||||
fn from_little_endian(self) -> Self;
|
||||
}
|
||||
type Scalar: private::TriviallyTransmutable;
|
||||
|
||||
/// Macro for implementing a no-op endian conversion. This is used for types
|
||||
/// that are one byte wide.
|
||||
macro_rules! impl_endian_scalar_noop {
|
||||
($ty:ident) => {
|
||||
impl EndianScalar for $ty {
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
fn from_little_endian(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
fn to_little_endian(self) -> Self::Scalar;
|
||||
|
||||
fn from_little_endian(v: Self::Scalar) -> Self;
|
||||
}
|
||||
|
||||
/// Macro for implementing an endian conversion using the stdlib `to_le` and
|
||||
/// `from_le` functions. This is used for integer types. It is not used for
|
||||
/// floats, because the `to_le` and `from_le` are not implemented for them in
|
||||
/// the stdlib.
|
||||
macro_rules! impl_endian_scalar_stdlib_le_conversion {
|
||||
macro_rules! impl_endian_scalar {
|
||||
($ty:ident) => {
|
||||
impl EndianScalar for $ty {
|
||||
type Scalar = Self;
|
||||
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
fn to_little_endian(self) -> Self::Scalar {
|
||||
Self::to_le(self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_little_endian(self) -> Self {
|
||||
Self::from_le(self)
|
||||
fn from_little_endian(v: Self::Scalar) -> Self {
|
||||
Self::from_le(v)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_endian_scalar_noop!(bool);
|
||||
impl_endian_scalar_noop!(u8);
|
||||
impl_endian_scalar_noop!(i8);
|
||||
impl_endian_scalar!(u8);
|
||||
impl_endian_scalar!(i8);
|
||||
impl_endian_scalar!(u16);
|
||||
impl_endian_scalar!(u32);
|
||||
impl_endian_scalar!(u64);
|
||||
impl_endian_scalar!(i16);
|
||||
impl_endian_scalar!(i32);
|
||||
impl_endian_scalar!(i64);
|
||||
|
||||
impl_endian_scalar_stdlib_le_conversion!(u16);
|
||||
impl_endian_scalar_stdlib_le_conversion!(u32);
|
||||
impl_endian_scalar_stdlib_le_conversion!(u64);
|
||||
impl_endian_scalar_stdlib_le_conversion!(i16);
|
||||
impl_endian_scalar_stdlib_le_conversion!(i32);
|
||||
impl_endian_scalar_stdlib_le_conversion!(i64);
|
||||
impl EndianScalar for bool {
|
||||
type Scalar = u8;
|
||||
|
||||
fn to_little_endian(self) -> Self::Scalar {
|
||||
self as u8
|
||||
}
|
||||
|
||||
fn from_little_endian(v: Self::Scalar) -> Self {
|
||||
v != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl EndianScalar for f32 {
|
||||
type Scalar = u32;
|
||||
/// Convert f32 from host endian-ness to little-endian.
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
byte_swap_f32(self)
|
||||
}
|
||||
fn to_little_endian(self) -> u32 {
|
||||
// Floats and Ints have the same endianness on all supported platforms.
|
||||
// <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
|
||||
self.to_bits().to_le()
|
||||
}
|
||||
/// Convert f32 from little-endian to host endian-ness.
|
||||
#[inline]
|
||||
fn from_little_endian(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
byte_swap_f32(self)
|
||||
}
|
||||
fn from_little_endian(v: u32) -> Self {
|
||||
// Floats and Ints have the same endianness on all supported platforms.
|
||||
// <https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits>
|
||||
f32::from_bits(u32::from_le(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl EndianScalar for f64 {
|
||||
type Scalar = u64;
|
||||
|
||||
/// Convert f64 from host endian-ness to little-endian.
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
byte_swap_f64(self)
|
||||
}
|
||||
fn to_little_endian(self) -> u64 {
|
||||
// Floats and Ints have the same endianness on all supported platforms.
|
||||
// <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
|
||||
self.to_bits().to_le()
|
||||
}
|
||||
/// Convert f64 from little-endian to host endian-ness.
|
||||
#[inline]
|
||||
fn from_little_endian(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
byte_swap_f64(self)
|
||||
}
|
||||
fn from_little_endian(v: u64) -> Self {
|
||||
// Floats and Ints have the same endianness on all supported platforms.
|
||||
// <https://doc.rust-lang.org/std/primitive.f64.html#method.from_bits>
|
||||
f64::from_bits(u64::from_le(v))
|
||||
}
|
||||
}
|
||||
|
||||
/// Swaps the bytes of an f32.
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn byte_swap_f32(x: f32) -> f32 {
|
||||
f32::from_bits(x.to_bits().swap_bytes())
|
||||
}
|
||||
|
||||
/// Swaps the bytes of an f64.
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn byte_swap_f64(x: f64) -> f64 {
|
||||
f64::from_bits(x.to_bits().swap_bytes())
|
||||
}
|
||||
|
||||
/// Place an EndianScalar into the provided mutable byte slice. Performs
|
||||
/// endian conversion, if necessary.
|
||||
/// # Safety
|
||||
/// Caller must ensure `s.len() > size_of::<T>()`
|
||||
/// and `x` does not overlap with `s`.
|
||||
/// Caller must ensure `s.len() >= size_of::<T>()`
|
||||
#[inline]
|
||||
pub unsafe fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
|
||||
let size = size_of::<T::Scalar>();
|
||||
debug_assert!(
|
||||
s.len() >= size,
|
||||
"insufficient capacity for emplace_scalar, needed {} got {}",
|
||||
size,
|
||||
s.len()
|
||||
);
|
||||
|
||||
let x_le = x.to_little_endian();
|
||||
core::ptr::copy_nonoverlapping(
|
||||
&x_le as *const T as *const u8,
|
||||
&x_le as *const T::Scalar as *const u8,
|
||||
s.as_mut_ptr() as *mut u8,
|
||||
size_of::<T>(),
|
||||
size,
|
||||
);
|
||||
}
|
||||
|
||||
/// Read an EndianScalar from the provided byte slice at the specified location.
|
||||
/// Performs endian conversion, if necessary.
|
||||
/// # Safety
|
||||
/// Caller must ensure `s.len() > loc + size_of::<T>()`.
|
||||
/// Caller must ensure `s.len() >= loc + size_of::<T>()`.
|
||||
#[inline]
|
||||
pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
||||
read_scalar(&s[loc..])
|
||||
@@ -177,8 +169,16 @@ pub unsafe fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
||||
/// Caller must ensure `s.len() > size_of::<T>()`.
|
||||
#[inline]
|
||||
pub unsafe fn read_scalar<T: EndianScalar>(s: &[u8]) -> T {
|
||||
let mut mem = core::mem::MaybeUninit::<T>::uninit();
|
||||
let size = size_of::<T::Scalar>();
|
||||
debug_assert!(
|
||||
s.len() >= size,
|
||||
"insufficient capacity for emplace_scalar, needed {} got {}",
|
||||
size,
|
||||
s.len()
|
||||
);
|
||||
|
||||
let mut mem = core::mem::MaybeUninit::<T::Scalar>::uninit();
|
||||
// Since [u8] has alignment 1, we copy it into T which may have higher alignment.
|
||||
core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size_of::<T>());
|
||||
mem.assume_init().from_little_endian()
|
||||
core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size);
|
||||
T::from_little_endian(mem.assume_init())
|
||||
}
|
||||
|
||||
@@ -29,7 +29,11 @@ use core::marker::PhantomData;
|
||||
/// continue traversing the FlatBuffer.
|
||||
pub trait Follow<'buf> {
|
||||
type Inner;
|
||||
fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
|
||||
/// # Safety
|
||||
///
|
||||
/// `buf[loc..]` must contain a valid value of `Self` and anything it
|
||||
/// transitively refers to by offset must also be valid
|
||||
unsafe fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
|
||||
}
|
||||
|
||||
/// FollowStart wraps a Follow impl in a struct type. This can make certain
|
||||
@@ -39,17 +43,21 @@ pub struct FollowStart<T>(PhantomData<T>);
|
||||
impl<'a, T: Follow<'a> + 'a> FollowStart<T> {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self { 0: PhantomData }
|
||||
Self(PhantomData)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `buf[loc..]` must contain a valid value of `T`
|
||||
#[inline]
|
||||
pub fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner {
|
||||
pub unsafe fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner {
|
||||
T::follow(buf, loc)
|
||||
}
|
||||
}
|
||||
impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
T::follow(buf, loc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ where
|
||||
{
|
||||
let mut v = Verifier::new(opts, data);
|
||||
<ForwardsUOffset<T>>::run_verifier(&mut v, 0)?;
|
||||
// Safety:
|
||||
// Run verifier above
|
||||
Ok(unsafe { root_unchecked::<T>(data) })
|
||||
}
|
||||
|
||||
@@ -75,6 +77,8 @@ where
|
||||
{
|
||||
let mut v = Verifier::new(opts, data);
|
||||
<SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?;
|
||||
// Safety:
|
||||
// Run verifier above
|
||||
Ok(unsafe { size_prefixed_root_unchecked::<T>(data) })
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
|
||||
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
|
||||
|
||||
#![cfg_attr(feature = "no_std", no_std)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
mod array;
|
||||
@@ -48,14 +49,12 @@ mod vtable_writer;
|
||||
|
||||
pub use crate::array::{array_init, emplace_scalar_array, Array};
|
||||
pub use crate::builder::FlatBufferBuilder;
|
||||
pub use crate::endian_scalar::{
|
||||
byte_swap_f32, byte_swap_f64, emplace_scalar, read_scalar, read_scalar_at, EndianScalar,
|
||||
};
|
||||
pub use crate::endian_scalar::{emplace_scalar, read_scalar, read_scalar_at, EndianScalar};
|
||||
pub use crate::follow::{Follow, FollowStart};
|
||||
pub use crate::primitives::*;
|
||||
pub use crate::push::Push;
|
||||
pub use crate::table::{buffer_has_identifier, Table};
|
||||
pub use crate::vector::{follow_cast_ref, SafeSliceAccess, Vector, VectorIter};
|
||||
pub use crate::vector::{follow_cast_ref, Vector, VectorIter};
|
||||
pub use crate::verifier::{
|
||||
ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier,
|
||||
VerifierOptions,
|
||||
@@ -64,6 +63,4 @@ pub use crate::vtable::field_index_to_field_offset;
|
||||
pub use bitflags;
|
||||
pub use get_root::*;
|
||||
|
||||
// TODO(rw): Unify `create_vector` and `create_vector_direct` by using
|
||||
// `Into<Vector<...>>`.
|
||||
// TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++.
|
||||
|
||||
@@ -112,10 +112,7 @@ impl<'a, T: 'a> WIPOffset<T> {
|
||||
/// Create a new WIPOffset.
|
||||
#[inline]
|
||||
pub fn new(o: UOffsetT) -> WIPOffset<T> {
|
||||
WIPOffset {
|
||||
0: o,
|
||||
1: PhantomData,
|
||||
}
|
||||
WIPOffset(o, PhantomData)
|
||||
}
|
||||
|
||||
/// Return a wrapped value that brings its meaning as a union WIPOffset
|
||||
@@ -135,11 +132,9 @@ impl<T> Push for WIPOffset<T> {
|
||||
type Output = ForwardsUOffset<T>;
|
||||
|
||||
#[inline(always)]
|
||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
||||
let n = (SIZE_UOFFSET + rest.len() - self.value() as usize) as UOffsetT;
|
||||
unsafe {
|
||||
emplace_scalar::<UOffsetT>(dst, n);
|
||||
}
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||
let n = (SIZE_UOFFSET + written_len - self.value() as usize) as UOffsetT;
|
||||
emplace_scalar::<UOffsetT>(dst, n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,8 +142,8 @@ impl<T> Push for ForwardsUOffset<T> {
|
||||
type Output = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
||||
self.value().push(dst, rest);
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||
self.value().push(dst, written_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,9 +174,9 @@ impl<T> ForwardsUOffset<T> {
|
||||
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let slice = &buf[loc..loc + SIZE_UOFFSET];
|
||||
let off = unsafe { read_scalar::<u32>(slice) as usize };
|
||||
let off = read_scalar::<u32>(slice) as usize;
|
||||
T::follow(buf, loc + off)
|
||||
}
|
||||
}
|
||||
@@ -200,9 +195,9 @@ impl<T> ForwardsVOffset<T> {
|
||||
impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let slice = &buf[loc..loc + SIZE_VOFFSET];
|
||||
let off = unsafe { read_scalar::<VOffsetT>(slice) as usize };
|
||||
let off = read_scalar::<VOffsetT>(slice) as usize;
|
||||
T::follow(buf, loc + off)
|
||||
}
|
||||
}
|
||||
@@ -211,8 +206,8 @@ impl<T> Push for ForwardsVOffset<T> {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
||||
self.value().push(dst, rest);
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||
self.value().push(dst, written_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,9 +225,9 @@ impl<T> BackwardsSOffset<T> {
|
||||
impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let slice = &buf[loc..loc + SIZE_SOFFSET];
|
||||
let off = unsafe { read_scalar::<SOffsetT>(slice) };
|
||||
let off = read_scalar::<SOffsetT>(slice);
|
||||
T::follow(buf, (loc as SOffsetT - off) as usize)
|
||||
}
|
||||
}
|
||||
@@ -241,8 +236,8 @@ impl<T> Push for BackwardsSOffset<T> {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn push(&self, dst: &mut [u8], rest: &[u8]) {
|
||||
self.value().push(dst, rest);
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||
self.value().push(dst, written_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +247,7 @@ pub struct SkipSizePrefix<T>(PhantomData<T>);
|
||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
T::follow(buf, loc + SIZE_SIZEPREFIX)
|
||||
}
|
||||
}
|
||||
@@ -263,7 +258,7 @@ pub struct SkipRootOffset<T>(PhantomData<T>);
|
||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
T::follow(buf, loc + SIZE_UOFFSET)
|
||||
}
|
||||
}
|
||||
@@ -274,7 +269,7 @@ pub struct FileIdentifier;
|
||||
impl<'a> Follow<'a> for FileIdentifier {
|
||||
type Inner = &'a [u8];
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
&buf[loc..loc + FILE_IDENTIFIER_LENGTH]
|
||||
}
|
||||
}
|
||||
@@ -286,7 +281,7 @@ pub struct SkipFileIdentifier<T>(PhantomData<T>);
|
||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
|
||||
type Inner = T::Inner;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
T::follow(buf, loc + FILE_IDENTIFIER_LENGTH)
|
||||
}
|
||||
}
|
||||
@@ -294,8 +289,8 @@ impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier<T> {
|
||||
impl<'a> Follow<'a> for bool {
|
||||
type Inner = bool;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe { read_scalar_at::<u8>(buf, loc) != 0 }
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
read_scalar_at::<u8>(buf, loc) != 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +304,8 @@ macro_rules! impl_follow_for_endian_scalar {
|
||||
impl<'a> Follow<'a> for $ty {
|
||||
type Inner = $ty;
|
||||
#[inline(always)]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe { read_scalar_at::<$ty>(buf, loc) }
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
read_scalar_at::<$ty>(buf, loc)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,7 +24,11 @@ use crate::endian_scalar::emplace_scalar;
|
||||
/// types.
|
||||
pub trait Push: Sized {
|
||||
type Output;
|
||||
fn push(&self, dst: &mut [u8], _rest: &[u8]);
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// dst is aligned to [`Self::alignment`] and has length greater than or equal to [`Self::size`]
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize);
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
size_of::<Self::Output>()
|
||||
@@ -35,13 +39,29 @@ pub trait Push: Sized {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Push> Push for &'a T {
|
||||
type Output = T::Output;
|
||||
|
||||
unsafe fn push(&self, dst: &mut [u8], written_len: usize) {
|
||||
T::push(self, dst, written_len)
|
||||
}
|
||||
|
||||
fn size() -> usize {
|
||||
T::size()
|
||||
}
|
||||
|
||||
fn alignment() -> PushAlignment {
|
||||
T::alignment()
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure Push alignment calculations are typesafe (because this helps reduce
|
||||
/// implementation issues when using FlatBufferBuilder::align).
|
||||
pub struct PushAlignment(usize);
|
||||
impl PushAlignment {
|
||||
#[inline]
|
||||
pub fn new(x: usize) -> Self {
|
||||
PushAlignment { 0: x }
|
||||
PushAlignment(x)
|
||||
}
|
||||
#[inline]
|
||||
pub fn value(&self) -> usize {
|
||||
@@ -60,10 +80,8 @@ macro_rules! impl_push_for_endian_scalar {
|
||||
type Output = $ty;
|
||||
|
||||
#[inline]
|
||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
||||
unsafe {
|
||||
emplace_scalar::<$ty>(dst, *self);
|
||||
}
|
||||
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||
emplace_scalar::<$ty>(dst, *self);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,23 +18,36 @@ use crate::follow::Follow;
|
||||
use crate::primitives::*;
|
||||
use crate::vtable::VTable;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Table<'a> {
|
||||
pub buf: &'a [u8],
|
||||
pub loc: usize,
|
||||
buf: &'a [u8],
|
||||
loc: usize,
|
||||
}
|
||||
|
||||
impl<'a> Table<'a> {
|
||||
/// # Safety
|
||||
///
|
||||
/// `buf` must contain a `soffset_t` at `loc`, which points to a valid vtable
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||
pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||
Table { buf, loc }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn vtable(&self) -> VTable<'a> {
|
||||
<BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc)
|
||||
// Safety:
|
||||
// Table::new is created with a valid buf and location
|
||||
unsafe { <BackwardsSOffset<VTable<'a>>>::follow(self.buf, self.loc) }
|
||||
}
|
||||
|
||||
/// Retrieves the value at the provided `slot_byte_loc` returning `default`
|
||||
/// if no value present
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The value of the corresponding slot must have type T
|
||||
#[inline]
|
||||
pub fn get<T: Follow<'a> + 'a>(
|
||||
pub unsafe fn get<T: Follow<'a> + 'a>(
|
||||
&self,
|
||||
slot_byte_loc: VOffsetT,
|
||||
default: Option<T::Inner>,
|
||||
@@ -50,19 +63,26 @@ impl<'a> Table<'a> {
|
||||
impl<'a> Follow<'a> for Table<'a> {
|
||||
type Inner = Table<'a>;
|
||||
#[inline]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Table { buf, loc }
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if data contains a prefix of `ident`
|
||||
#[inline]
|
||||
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool {
|
||||
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
|
||||
|
||||
let got = if size_prefixed {
|
||||
<SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0)
|
||||
assert!(data.len() >= SIZE_SIZEPREFIX + SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
|
||||
// Safety:
|
||||
// Verified data has sufficient bytes
|
||||
unsafe { <SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0) }
|
||||
} else {
|
||||
<SkipRootOffset<FileIdentifier>>::follow(data, 0)
|
||||
assert!(data.len() >= SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH);
|
||||
// Safety:
|
||||
// Verified data has sufficient bytes
|
||||
unsafe { <SkipRootOffset<FileIdentifier>>::follow(data, 0) }
|
||||
};
|
||||
|
||||
ident.as_bytes() == got
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
use core::fmt::{Debug, Formatter, Result};
|
||||
use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::size_of;
|
||||
use core::slice::from_raw_parts;
|
||||
use core::mem::{align_of, size_of};
|
||||
use core::str::from_utf8_unchecked;
|
||||
|
||||
use crate::endian_scalar::read_scalar_at;
|
||||
#[cfg(target_endian = "little")]
|
||||
use crate::endian_scalar::EndianScalar;
|
||||
use crate::follow::Follow;
|
||||
use crate::primitives::*;
|
||||
|
||||
@@ -55,6 +52,7 @@ where
|
||||
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
|
||||
// can always be copied, no matter that `T` you have.
|
||||
impl<'a, T> Copy for Vector<'a, T> {}
|
||||
|
||||
impl<'a, T> Clone for Vector<'a, T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@@ -62,32 +60,46 @@ impl<'a, T> Clone for Vector<'a, T> {
|
||||
}
|
||||
|
||||
impl<'a, T: 'a> Vector<'a, T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// `buf` contains a valid vector at `loc` consisting of
|
||||
///
|
||||
/// - UOffsetT element count
|
||||
/// - Consecutive list of `T` elements
|
||||
#[inline(always)]
|
||||
pub fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||
Vector {
|
||||
0: buf,
|
||||
1: loc,
|
||||
2: PhantomData,
|
||||
}
|
||||
pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self {
|
||||
Vector(buf, loc, PhantomData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn len(&self) -> usize {
|
||||
// Safety:
|
||||
// Valid vector at time of construction starting with UOffsetT element count
|
||||
unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn bytes(&self) -> &'a [u8] {
|
||||
let sz = size_of::<T>();
|
||||
let len = self.len();
|
||||
&self.0[self.1 + SIZE_UOFFSET..self.1 + SIZE_UOFFSET + sz * len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
|
||||
#[inline(always)]
|
||||
pub fn get(&self, idx: usize) -> T::Inner {
|
||||
assert!(idx < self.len() as usize);
|
||||
assert!(idx < self.len());
|
||||
let sz = size_of::<T>();
|
||||
debug_assert!(sz > 0);
|
||||
T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx)
|
||||
// Safety:
|
||||
// Valid vector at time of construction, verified that idx < element count
|
||||
unsafe { T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -96,84 +108,40 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SafeSliceAccess {}
|
||||
impl<'a, T: SafeSliceAccess + 'a> Vector<'a, T> {
|
||||
pub fn safe_slice(self) -> &'a [T] {
|
||||
let buf = self.0;
|
||||
let loc = self.1;
|
||||
let sz = size_of::<T>();
|
||||
debug_assert!(sz > 0);
|
||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
|
||||
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
|
||||
let ptr = data_buf.as_ptr() as *const T;
|
||||
let s: &'a [T] = unsafe { from_raw_parts(ptr, len) };
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl SafeSliceAccess for u8 {}
|
||||
impl SafeSliceAccess for i8 {}
|
||||
impl SafeSliceAccess for bool {}
|
||||
|
||||
// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity.
|
||||
// Vectors of primitives just don't work on big endian machines!!!
|
||||
#[cfg(target_endian = "little")]
|
||||
mod le_safe_slice_impls {
|
||||
impl super::SafeSliceAccess for u16 {}
|
||||
impl super::SafeSliceAccess for u32 {}
|
||||
impl super::SafeSliceAccess for u64 {}
|
||||
|
||||
impl super::SafeSliceAccess for i16 {}
|
||||
impl super::SafeSliceAccess for i32 {}
|
||||
impl super::SafeSliceAccess for i64 {}
|
||||
|
||||
impl super::SafeSliceAccess for f32 {}
|
||||
impl super::SafeSliceAccess for f64 {}
|
||||
}
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
pub use self::le_safe_slice_impls::*;
|
||||
|
||||
pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
|
||||
/// # Safety
|
||||
///
|
||||
/// `buf` must contain a value of T at `loc` and have alignment of 1
|
||||
pub unsafe fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
|
||||
assert_eq!(align_of::<T>(), 1);
|
||||
let sz = size_of::<T>();
|
||||
let buf = &buf[loc..loc + sz];
|
||||
let ptr = buf.as_ptr() as *const T;
|
||||
unsafe { &*ptr }
|
||||
// SAFETY
|
||||
// buf contains a value at loc of type T and T has no alignment requirements
|
||||
&*ptr
|
||||
}
|
||||
|
||||
impl<'a> Follow<'a> for &'a str {
|
||||
type Inner = &'a str;
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
|
||||
let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
|
||||
unsafe { from_utf8_unchecked(slice) }
|
||||
from_utf8_unchecked(slice)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
|
||||
let sz = size_of::<T>();
|
||||
debug_assert!(sz > 0);
|
||||
let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) as usize };
|
||||
let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
|
||||
let ptr = data_buf.as_ptr() as *const T;
|
||||
let s: &[T] = unsafe { from_raw_parts(ptr, len) };
|
||||
s
|
||||
}
|
||||
|
||||
/// Implement direct slice access if the host is little-endian.
|
||||
#[cfg(target_endian = "little")]
|
||||
impl<'a, T: EndianScalar> Follow<'a> for &'a [T] {
|
||||
type Inner = &'a [T];
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
follow_slice_helper::<T>(buf, loc)
|
||||
impl<'a> Follow<'a> for &'a [u8] {
|
||||
type Inner = &'a [u8];
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
|
||||
&buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement Follow for all possible Vectors that have Follow-able elements.
|
||||
impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> {
|
||||
type Inner = Vector<'a, T>;
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Vector::new(buf, loc)
|
||||
}
|
||||
}
|
||||
@@ -201,8 +169,14 @@ impl<'a, T: 'a> VectorIter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `VectorIter` from the provided slice
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// buf must contain a contiguous sequence of `items_num` values of `T`
|
||||
///
|
||||
#[inline]
|
||||
pub fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
|
||||
pub unsafe fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
|
||||
VectorIter {
|
||||
buf,
|
||||
loc: 0,
|
||||
@@ -235,7 +209,10 @@ impl<'a, T: Follow<'a> + 'a> Iterator for VectorIter<'a, T> {
|
||||
if self.remaining == 0 {
|
||||
None
|
||||
} else {
|
||||
let result = T::follow(self.buf, self.loc);
|
||||
// Safety:
|
||||
// VectorIter can only be created from a contiguous sequence of `items_num`
|
||||
// And remaining is initialized to `items_num`
|
||||
let result = unsafe { T::follow(self.buf, self.loc) };
|
||||
self.loc += sz;
|
||||
self.remaining -= 1;
|
||||
Some(result)
|
||||
@@ -272,7 +249,10 @@ impl<'a, T: Follow<'a> + 'a> DoubleEndedIterator for VectorIter<'a, T> {
|
||||
None
|
||||
} else {
|
||||
self.remaining -= 1;
|
||||
Some(T::follow(self.buf, self.loc + sz * self.remaining))
|
||||
// Safety:
|
||||
// VectorIter can only be created from a contiguous sequence of `items_num`
|
||||
// And remaining is initialized to `items_num`
|
||||
Some(unsafe { T::follow(self.buf, self.loc + sz * self.remaining) })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +289,7 @@ impl<'a, 'b, T: Follow<'a> + 'a> IntoIterator for &'b Vector<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="serialize")]
|
||||
#[cfg(feature = "serialize")]
|
||||
impl<'a, T> serde::ser::Serialize for Vector<'a, T>
|
||||
where
|
||||
T: 'a + Follow<'a>,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#[cfg(feature = "no_std")]
|
||||
use crate::follow::Follow;
|
||||
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::Range;
|
||||
use core::option::Option;
|
||||
use crate::follow::Follow;
|
||||
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
|
||||
|
||||
#[cfg(feature="no_std")]
|
||||
use thiserror_core2::Error;
|
||||
#[cfg(not(feature="no_std"))]
|
||||
use thiserror::Error;
|
||||
#[cfg(all(nightly, not(feature = "std")))]
|
||||
use core::error::Error;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
/// Traces the location of data errors. Not populated for Dos detecting errors.
|
||||
/// Useful for MissingRequiredField and Utf8Error in particular, though
|
||||
@@ -28,8 +28,10 @@ pub enum ErrorTraceDetail {
|
||||
position: usize,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Default, Debug, Clone)]
|
||||
pub struct ErrorTrace(Vec<ErrorTraceDetail>);
|
||||
|
||||
impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[ErrorTraceDetail] {
|
||||
@@ -39,64 +41,138 @@ impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
||||
|
||||
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
|
||||
/// information is given for DoS detecting errors since it will probably be a lot.
|
||||
#[derive(Clone, Error, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InvalidFlatbuffer {
|
||||
#[error("Missing required field `{required}`.\n{error_trace}")]
|
||||
MissingRequiredField {
|
||||
required: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error(
|
||||
"Union exactly one of union discriminant (`{field_type}`) and value \
|
||||
(`{field}`) are present.\n{error_trace}"
|
||||
)]
|
||||
InconsistentUnion {
|
||||
field: &'static str,
|
||||
field_type: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
|
||||
Utf8Error {
|
||||
#[source]
|
||||
error: core::str::Utf8Error,
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
|
||||
range.start, range.end)]
|
||||
MissingNullTerminator {
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
|
||||
Unaligned {
|
||||
position: usize,
|
||||
unaligned_type: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
|
||||
RangeOutOfBounds {
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error(
|
||||
"Signed offset at position {position} has value {soffset} which points out of bounds.\
|
||||
\n{error_trace}"
|
||||
)]
|
||||
SignedOffsetOutOfBounds {
|
||||
soffset: SOffsetT,
|
||||
position: usize,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
// Dos detecting errors. These do not get error traces since it will probably be very large.
|
||||
#[error("Too many tables.")]
|
||||
TooManyTables,
|
||||
#[error("Apparent size too large.")]
|
||||
ApparentSizeTooLarge,
|
||||
#[error("Nested table depth limit reached.")]
|
||||
DepthLimitReached,
|
||||
}
|
||||
|
||||
#[cfg(any(nightly, feature = "std"))]
|
||||
impl Error for InvalidFlatbuffer {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
if let InvalidFlatbuffer::Utf8Error { error: source, .. } = self {
|
||||
Some(source)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for InvalidFlatbuffer {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match self {
|
||||
InvalidFlatbuffer::MissingRequiredField {
|
||||
required,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(f, "Missing required field `{}`.\n{}", required, error_trace)?;
|
||||
}
|
||||
InvalidFlatbuffer::InconsistentUnion {
|
||||
field,
|
||||
field_type,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Exactly one of union discriminant (`{}`) and value (`{}`) are present.\n{}",
|
||||
field_type, field, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::Utf8Error {
|
||||
error,
|
||||
range,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Utf8 error for string in {:?}: {}\n{}",
|
||||
range, error, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::MissingNullTerminator { range, error_trace } => {
|
||||
writeln!(
|
||||
f,
|
||||
"String in range [{}, {}) is missing its null terminator.\n{}",
|
||||
range.start, range.end, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::Unaligned {
|
||||
position,
|
||||
unaligned_type,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Type `{}` at position {} is unaligned.\n{}",
|
||||
unaligned_type, position, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::RangeOutOfBounds { range, error_trace } => {
|
||||
writeln!(
|
||||
f,
|
||||
"Range [{}, {}) is out of bounds.\n{}",
|
||||
range.start, range.end, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::SignedOffsetOutOfBounds {
|
||||
soffset,
|
||||
position,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Signed offset at position {} has value {} which points out of bounds.\n{}",
|
||||
position, soffset, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::TooManyTables {} => {
|
||||
writeln!(f, "Too many tables.")?;
|
||||
}
|
||||
InvalidFlatbuffer::ApparentSizeTooLarge {} => {
|
||||
writeln!(f, "Apparent size too large.")?;
|
||||
}
|
||||
InvalidFlatbuffer::DepthLimitReached {} => {
|
||||
writeln!(f, "Nested table depth limit reached.")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for ErrorTrace {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
use ErrorTraceDetail::*;
|
||||
@@ -184,6 +260,7 @@ fn trace_field<T>(res: Result<T>, field_name: &'static str, position: usize) ->
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Adds a TableField trace detail if `res` is a data error.
|
||||
fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> {
|
||||
append_trace(res, ErrorTraceDetail::VectorElement { index, position })
|
||||
@@ -205,6 +282,7 @@ pub struct VerifierOptions {
|
||||
// options to error un-recognized enums and unions? possible footgun.
|
||||
// Ignore nested flatbuffers, etc?
|
||||
}
|
||||
|
||||
impl Default for VerifierOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -226,6 +304,7 @@ pub struct Verifier<'opts, 'buf> {
|
||||
num_tables: usize,
|
||||
apparent_size: usize,
|
||||
}
|
||||
|
||||
impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||
pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self {
|
||||
Self {
|
||||
@@ -247,9 +326,12 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||
/// memory since `buffer: &[u8]` has alignment 1.
|
||||
///
|
||||
/// ### WARNING
|
||||
///
|
||||
/// This does not work for flatbuffers-structs as they have alignment 1 according to
|
||||
/// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t.
|
||||
/// `buffer[0]`. TODO(caspern).
|
||||
///
|
||||
/// Note this does not impact soundness as this crate does not assume alignment of structs
|
||||
#[inline]
|
||||
fn is_aligned<T>(&self, pos: usize) -> Result<()> {
|
||||
if pos % core::mem::align_of::<T>() == 0 {
|
||||
@@ -307,9 +389,9 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||
|
||||
// signed offsets are subtracted.
|
||||
let derefed = if offset > 0 {
|
||||
pos.checked_sub(offset.abs() as usize)
|
||||
pos.checked_sub(offset.unsigned_abs() as usize)
|
||||
} else {
|
||||
pos.checked_add(offset.abs() as usize)
|
||||
pos.checked_add(offset.unsigned_abs() as usize)
|
||||
};
|
||||
if let Some(x) = derefed {
|
||||
if x < self.buffer.len() {
|
||||
@@ -372,6 +454,7 @@ pub struct TableVerifier<'ver, 'opts, 'buf> {
|
||||
// Verifier struct which holds the surrounding state and options.
|
||||
verifier: &'ver mut Verifier<'opts, 'buf>,
|
||||
}
|
||||
|
||||
impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
|
||||
fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> {
|
||||
let field = field as usize;
|
||||
@@ -439,7 +522,9 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
|
||||
}
|
||||
(Some(k), Some(v)) => {
|
||||
trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?;
|
||||
let discriminant = Key::follow(self.verifier.buffer, k);
|
||||
// Safety:
|
||||
// Run verifier on `k` above
|
||||
let discriminant = unsafe { Key::follow(self.verifier.buffer, k) };
|
||||
trace_field(
|
||||
verify_union(discriminant, self.verifier, v),
|
||||
val_field_name,
|
||||
@@ -486,16 +571,27 @@ fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<core::ops::Ran
|
||||
}
|
||||
|
||||
pub trait SimpleToVerifyInSlice {}
|
||||
|
||||
impl SimpleToVerifyInSlice for bool {}
|
||||
|
||||
impl SimpleToVerifyInSlice for i8 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for u8 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for i16 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for u16 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for i32 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for u32 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for f32 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for i64 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for u64 {}
|
||||
|
||||
impl SimpleToVerifyInSlice for f64 {}
|
||||
|
||||
impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> {
|
||||
|
||||
@@ -33,24 +33,42 @@ impl<'a> PartialEq for VTable<'a> {
|
||||
}
|
||||
|
||||
impl<'a> VTable<'a> {
|
||||
pub fn init(buf: &'a [u8], loc: usize) -> Self {
|
||||
/// SAFETY
|
||||
/// `buf` must contain a valid vtable at `loc`
|
||||
///
|
||||
/// This consists of a number of `VOffsetT`
|
||||
/// - size of vtable in bytes including size element
|
||||
/// - size of object in bytes including the vtable offset
|
||||
/// - n fields where n is the number of fields in the table's schema when the code was compiled
|
||||
pub unsafe fn init(buf: &'a [u8], loc: usize) -> Self {
|
||||
VTable { buf, loc }
|
||||
}
|
||||
|
||||
pub fn num_fields(&self) -> usize {
|
||||
(self.num_bytes() / SIZE_VOFFSET) - 2
|
||||
}
|
||||
|
||||
pub fn num_bytes(&self) -> usize {
|
||||
// Safety:
|
||||
// Valid VTable at time of construction
|
||||
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc) as usize }
|
||||
}
|
||||
|
||||
pub fn object_inline_num_bytes(&self) -> usize {
|
||||
// Safety:
|
||||
// Valid VTable at time of construction
|
||||
let n = unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + SIZE_VOFFSET) };
|
||||
n as usize
|
||||
}
|
||||
|
||||
pub fn get_field(&self, idx: usize) -> VOffsetT {
|
||||
// TODO(rw): distinguish between None and 0?
|
||||
if idx > self.num_fields() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Safety:
|
||||
// Valid VTable at time of construction
|
||||
unsafe {
|
||||
read_scalar_at::<VOffsetT>(
|
||||
self.buf,
|
||||
@@ -58,13 +76,17 @@ impl<'a> VTable<'a> {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT {
|
||||
// TODO(rw): distinguish between None and 0?
|
||||
if byte_loc as usize >= self.num_bytes() {
|
||||
if byte_loc as usize + 2 > self.num_bytes() {
|
||||
return 0;
|
||||
}
|
||||
// Safety:
|
||||
// byte_loc is within bounds of vtable, which was valid at time of construction
|
||||
unsafe { read_scalar_at::<VOffsetT>(self.buf, self.loc + byte_loc as usize) }
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
let len = self.num_bytes();
|
||||
&self.buf[self.loc..self.loc + len]
|
||||
@@ -87,7 +109,7 @@ pub fn field_offset_to_field_index(field_o: VOffsetT) -> VOffsetT {
|
||||
|
||||
impl<'a> Follow<'a> for VTable<'a> {
|
||||
type Inner = VTable<'a>;
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
VTable::init(buf, loc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,11 @@ impl<'a> VTableWriter<'a> {
|
||||
/// to the provided value.
|
||||
#[inline(always)]
|
||||
pub fn write_vtable_byte_length(&mut self, n: VOffsetT) {
|
||||
let buf = &mut self.buf[..SIZE_VOFFSET];
|
||||
// Safety:
|
||||
// Validated range above
|
||||
unsafe {
|
||||
emplace_scalar::<VOffsetT>(&mut self.buf[..SIZE_VOFFSET], n);
|
||||
emplace_scalar::<VOffsetT>(buf, n);
|
||||
}
|
||||
debug_assert_eq!(n as usize, self.buf.len());
|
||||
}
|
||||
@@ -49,8 +52,11 @@ impl<'a> VTableWriter<'a> {
|
||||
/// Writes an object length (in bytes) into the vtable.
|
||||
#[inline(always)]
|
||||
pub fn write_object_inline_size(&mut self, n: VOffsetT) {
|
||||
let buf = &mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET];
|
||||
// Safety:
|
||||
// Validated range above
|
||||
unsafe {
|
||||
emplace_scalar::<VOffsetT>(&mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET], n);
|
||||
emplace_scalar::<VOffsetT>(buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +67,11 @@ impl<'a> VTableWriter<'a> {
|
||||
#[inline(always)]
|
||||
pub fn write_field_offset(&mut self, vtable_offset: VOffsetT, object_data_offset: VOffsetT) {
|
||||
let idx = vtable_offset as usize;
|
||||
let buf = &mut self.buf[idx..idx + SIZE_VOFFSET];
|
||||
// Safety:
|
||||
// Validated range above
|
||||
unsafe {
|
||||
emplace_scalar::<VOffsetT>(&mut self.buf[idx..idx + SIZE_VOFFSET], object_data_offset);
|
||||
emplace_scalar::<VOffsetT>(buf, object_data_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +82,9 @@ impl<'a> VTableWriter<'a> {
|
||||
// This is the closest thing to memset in Rust right now.
|
||||
let len = self.buf.len();
|
||||
let p = self.buf.as_mut_ptr() as *mut u8;
|
||||
|
||||
// Safety:
|
||||
// p is byte aligned and of length `len`
|
||||
unsafe {
|
||||
write_bytes(p, 0, len);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl<'de> Buffer for &'de [u8] {
|
||||
/// Based off of the `empty` function, allows override for optimization purposes.
|
||||
#[inline]
|
||||
fn empty_str() -> Self::BufferString {
|
||||
&""
|
||||
""
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -49,7 +49,7 @@ impl<'a> MapBuilder<'a> {
|
||||
// Nested vector.
|
||||
let start = Some(self.builder.values.len());
|
||||
VectorBuilder {
|
||||
builder: &mut self.builder,
|
||||
builder: self.builder,
|
||||
start,
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ impl<'a> MapBuilder<'a> {
|
||||
// Nested map.
|
||||
let start = Some(self.builder.values.len());
|
||||
MapBuilder {
|
||||
builder: &mut self.builder,
|
||||
builder: self.builder,
|
||||
start,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ impl ser::Error for Error {
|
||||
Self::Serde(format!("{}", msg))
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeSeq for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeSeq for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
@@ -113,14 +113,14 @@ impl<'a> ser::SerializeSeq for &mut FlexbufferSerializer {
|
||||
}
|
||||
// This is unlike a flexbuffers map which requires CString like keys.
|
||||
// Its implemented as alternating keys and values (hopefully).
|
||||
impl<'a> ser::SerializeMap for &'a mut FlexbufferSerializer {
|
||||
impl ser::SerializeMap for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
key.serialize(MapKeySerializer(&mut **self))
|
||||
key.serialize(MapKeySerializer(self))
|
||||
}
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
@@ -132,7 +132,7 @@ impl<'a> ser::SerializeMap for &'a mut FlexbufferSerializer {
|
||||
self.end_map()
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeTuple for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeTuple for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
@@ -145,7 +145,7 @@ impl<'a> ser::SerializeTuple for &mut FlexbufferSerializer {
|
||||
self.end_vector()
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
@@ -158,7 +158,7 @@ impl<'a> ser::SerializeTupleStruct for &mut FlexbufferSerializer {
|
||||
self.end_vector()
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeStruct for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeStruct for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_field<T: ?Sized>(
|
||||
@@ -176,7 +176,7 @@ impl<'a> ser::SerializeStruct for &mut FlexbufferSerializer {
|
||||
self.end_map()
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
@@ -190,7 +190,7 @@ impl<'a> ser::SerializeTupleVariant for &mut FlexbufferSerializer {
|
||||
self.end_map()
|
||||
}
|
||||
}
|
||||
impl<'a> ser::SerializeStructVariant for &mut FlexbufferSerializer {
|
||||
impl ser::SerializeStructVariant for &mut FlexbufferSerializer {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
fn serialize_field<T: ?Sized>(
|
||||
|
||||
@@ -39,7 +39,7 @@ impl<'a> VectorBuilder<'a> {
|
||||
pub fn start_vector(&mut self) -> VectorBuilder {
|
||||
let start = Some(self.builder.values.len());
|
||||
VectorBuilder {
|
||||
builder: &mut self.builder,
|
||||
builder: self.builder,
|
||||
start,
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ impl<'a> VectorBuilder<'a> {
|
||||
pub fn start_map(&mut self) -> MapBuilder {
|
||||
let start = Some(self.builder.values.len());
|
||||
MapBuilder {
|
||||
builder: &mut self.builder,
|
||||
builder: self.builder,
|
||||
start,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
// Serde with maps - field names and type names.
|
||||
|
||||
// Until flat/flexbuffers is on Rust v1.42, we cannot use the previously unstable matches! macro.
|
||||
#![allow(clippy::unknown_clippy_lints)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(clippy::match_like_matches_macro)]
|
||||
|
||||
#[macro_use]
|
||||
|
||||
@@ -380,7 +380,7 @@ impl<B: Buffer> Reader<B> {
|
||||
}
|
||||
|
||||
pub fn as_blob(&self) -> Blob<B> {
|
||||
self.get_blob().unwrap_or(Blob(B::empty()))
|
||||
self.get_blob().unwrap_or_else(|_| Blob(B::empty()))
|
||||
}
|
||||
|
||||
/// Retrieves str pointer, errors if invalid UTF-8, or the provided index
|
||||
@@ -580,8 +580,8 @@ impl<B: Buffer> Reader<B> {
|
||||
/// Returns empty string if you're not trying to read a string.
|
||||
pub fn as_str(&self) -> B::BufferString {
|
||||
match self.fxb_type {
|
||||
FlexBufferType::String => self.get_str().unwrap_or(B::empty_str()),
|
||||
FlexBufferType::Key => self.get_key().unwrap_or(B::empty_str()),
|
||||
FlexBufferType::String => self.get_str().unwrap_or_else(|_| B::empty_str()),
|
||||
FlexBufferType::Key => self.get_key().unwrap_or_else(|_| B::empty_str()),
|
||||
_ => B::empty_str(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// To run, use the `csharp_sample.sh` script.
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using Google.FlatBuffers;
|
||||
using MyGame.Sample;
|
||||
|
||||
class SampleBinary
|
||||
|
||||
Binary file not shown.
@@ -9,8 +9,8 @@
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 9 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 24,
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 6,
|
||||
"Non-compatible flatbuffers version included");
|
||||
|
||||
namespace MyGame {
|
||||
|
||||
@@ -31,7 +31,7 @@ public enum MyGame_Sample_Equipment: UInt8, Enum {
|
||||
|
||||
public struct MyGame_Sample_Vec3: NativeStruct {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
|
||||
private var _x: Float32
|
||||
private var _y: Float32
|
||||
@@ -56,7 +56,7 @@ public struct MyGame_Sample_Vec3: NativeStruct {
|
||||
|
||||
public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Struct
|
||||
|
||||
@@ -72,7 +72,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferObject {
|
||||
|
||||
public struct MyGame_Sample_Monster: FlatBufferObject {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
@@ -162,7 +162,7 @@ public struct MyGame_Sample_Monster: FlatBufferObject {
|
||||
|
||||
public struct MyGame_Sample_Weapon: FlatBufferObject {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_22_9_24() }
|
||||
static func validateVersion() { FlatBuffersVersion_22_12_06() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
|
||||
@@ -59,10 +59,8 @@ impl core::fmt::Debug for Color {
|
||||
impl<'a> flatbuffers::Follow<'a> for Color {
|
||||
type Inner = Self;
|
||||
#[inline]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let b = unsafe {
|
||||
flatbuffers::read_scalar_at::<i8>(buf, loc)
|
||||
};
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
|
||||
Self(b)
|
||||
}
|
||||
}
|
||||
@@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for Color {
|
||||
impl flatbuffers::Push for Color {
|
||||
type Output = Color;
|
||||
#[inline]
|
||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
||||
unsafe { flatbuffers::emplace_scalar::<i8>(dst, self.0); }
|
||||
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||
flatbuffers::emplace_scalar::<i8>(dst, self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl flatbuffers::EndianScalar for Color {
|
||||
type Scalar = i8;
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
let b = i8::to_le(self.0);
|
||||
Self(b)
|
||||
fn to_little_endian(self) -> i8 {
|
||||
self.0.to_le()
|
||||
}
|
||||
#[inline]
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn from_little_endian(self) -> Self {
|
||||
let b = i8::from_le(self.0);
|
||||
fn from_little_endian(v: i8) -> Self {
|
||||
let b = i8::from_le(v);
|
||||
Self(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +55,8 @@ impl core::fmt::Debug for Equipment {
|
||||
impl<'a> flatbuffers::Follow<'a> for Equipment {
|
||||
type Inner = Self;
|
||||
#[inline]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let b = unsafe {
|
||||
flatbuffers::read_scalar_at::<u8>(buf, loc)
|
||||
};
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
|
||||
Self(b)
|
||||
}
|
||||
}
|
||||
@@ -66,21 +64,21 @@ impl<'a> flatbuffers::Follow<'a> for Equipment {
|
||||
impl flatbuffers::Push for Equipment {
|
||||
type Output = Equipment;
|
||||
#[inline]
|
||||
fn push(&self, dst: &mut [u8], _rest: &[u8]) {
|
||||
unsafe { flatbuffers::emplace_scalar::<u8>(dst, self.0); }
|
||||
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
|
||||
flatbuffers::emplace_scalar::<u8>(dst, self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl flatbuffers::EndianScalar for Equipment {
|
||||
type Scalar = u8;
|
||||
#[inline]
|
||||
fn to_little_endian(self) -> Self {
|
||||
let b = u8::to_le(self.0);
|
||||
Self(b)
|
||||
fn to_little_endian(self) -> u8 {
|
||||
self.0.to_le()
|
||||
}
|
||||
#[inline]
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn from_little_endian(self) -> Self {
|
||||
let b = u8::from_le(self.0);
|
||||
fn from_little_endian(v: u8) -> Self {
|
||||
let b = u8::from_le(v);
|
||||
Self(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ pub struct Monster<'a> {
|
||||
impl<'a> flatbuffers::Follow<'a> for Monster<'a> {
|
||||
type Inner = Monster<'a>;
|
||||
#[inline]
|
||||
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Self { _tab: flatbuffers::Table { buf, loc } }
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ impl<'a> Monster<'a> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
Monster { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
@@ -73,7 +73,7 @@ impl<'a> Monster<'a> {
|
||||
x.to_string()
|
||||
});
|
||||
let inventory = self.inventory().map(|x| {
|
||||
x.to_vec()
|
||||
x.into_iter().collect()
|
||||
});
|
||||
let color = self.color();
|
||||
let weapons = self.weapons().map(|x| {
|
||||
@@ -106,49 +106,84 @@ impl<'a> Monster<'a> {
|
||||
|
||||
#[inline]
|
||||
pub fn pos(&self) -> Option<&'a Vec3> {
|
||||
self._tab.get::<Vec3>(Monster::VT_POS, None)
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<Vec3>(Monster::VT_POS, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn mana(&self) -> i16 {
|
||||
self._tab.get::<i16>(Monster::VT_MANA, Some(150)).unwrap()
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i16>(Monster::VT_MANA, Some(150)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn hp(&self) -> i16 {
|
||||
self._tab.get::<i16>(Monster::VT_HP, Some(100)).unwrap()
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i16>(Monster::VT_HP, Some(100)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<&'a str> {
|
||||
self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None)
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn inventory(&self) -> Option<&'a [u8]> {
|
||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(Monster::VT_INVENTORY, None).map(|v| v.safe_slice())
|
||||
pub fn inventory(&self) -> Option<flatbuffers::Vector<'a, u8>> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(Monster::VT_INVENTORY, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn color(&self) -> Color {
|
||||
self._tab.get::<Color>(Monster::VT_COLOR, Some(Color::Blue)).unwrap()
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<Color>(Monster::VT_COLOR, Some(Color::Blue)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn weapons(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon<'a>>>> {
|
||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None)
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn equipped_type(&self) -> Equipment {
|
||||
self._tab.get::<Equipment>(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap()
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<Equipment>(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn equipped(&self) -> Option<flatbuffers::Table<'a>> {
|
||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Monster::VT_EQUIPPED, None)
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Monster::VT_EQUIPPED, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn path(&self) -> Option<&'a [Vec3]> {
|
||||
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice())
|
||||
pub fn path(&self) -> Option<flatbuffers::Vector<'a, Vec3>> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None)}
|
||||
}
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn equipped_as_weapon(&self) -> Option<Weapon<'a>> {
|
||||
if self.equipped_type() == Equipment::Weapon {
|
||||
self.equipped().map(Weapon::init_from_table)
|
||||
self.equipped().map(|t| {
|
||||
// Safety:
|
||||
// Created from a valid Table for this object
|
||||
// Which contains a valid union in this slot
|
||||
unsafe { Weapon::init_from_table(t) }
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -365,18 +400,6 @@ impl MonsterT {
|
||||
})
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
||||
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
|
||||
unsafe { flatbuffers::root_unchecked::<Monster<'a>>(buf) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
||||
pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
|
||||
unsafe { flatbuffers::size_prefixed_root_unchecked::<Monster<'a>>(buf) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Verifies that a buffer of bytes contains a `Monster`
|
||||
/// and returns it.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user