Compare commits

..
6 Commits
Author SHA1 Message Date
Artyom Palvelev 5eb190f000 rust: fix 64-bit scalar wire-format alignment on 32-bit targets in Push::alignment (#9465)
In the FlatBuffers binary wire format specification, every scalar field is
aligned to its own byte size (`1`, `2`, `4`, or `8` bytes), regardless of the
host CPU architecture. Both the `flatc` schema compiler (when computing table
`max_align` and struct field offsets) and the C++ `FlatBufferBuilder::Align` /
`PushElement` implementation align 64-bit scalars (`u64`, `i64`, `f64`) to 8
bytes on all architectures.

However, in the Rust `flatbuffers` crate (`rust/flatbuffers/src/push.rs`), the
`Push` trait provides a default implementation:

```rust
fn alignment() -> PushAlignment {
    PushAlignment::new(align_of::<Self::Output>())
}
```

And `impl_push_for_endian_scalar!` did not override `Push::alignment()`,
inheriting `core::mem::align_of::<T>()` for all primitive scalar types (`bool`,
`u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `f32`, `f64`).

On 64-bit targets (`x86_64`, `aarch64`) and 32-bit ARM (`armv7`),
`align_of::<u64>() == 8`, so `align_of::<T>()` happens to equal `size_of::<T>()`.
On 32-bit x86 (`i686`, System V i386 ABI), however, the host ABI alignment of
64-bit scalars (`u64`, `i64`, `f64`) is **4 bytes** (`align_of::<u64>() == 4`),
while their FlatBuffer wire-format size and required wire alignment is **8
bytes** (`size_of::<u64>() == 8`).

As a consequence, on 32-bit x86 (`i686`):
1. `FlatBufferBuilder::push::<u64 / i64 / f64>` only aligns the builder's cursor
   and tracks `min_align` to 4 bytes instead of 8 bytes when writing 64-bit
   table fields or vectors of 64-bit scalars.
2. When a table containing a 64-bit scalar field (`uint64`, `int64`, `double`)
   is serialized on `i686`, the field can be placed at a buffer offset that is
   4-byte aligned but not 8-byte aligned.
3. When the resulting FlatBuffer is verified by C++ `flatbuffers::Verifier`
   (which checks `VerifyField<uint64_t>` with `sizeof(uint64_t) == 8` alignment
   when `FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE` / alignment checks are active)
   or transferred to a 64-bit reader, verification fails or unaligned 64-bit
   reads occur.

Fix `impl_push_for_endian_scalar!` to explicitly implement `Push::alignment()`
using `size_of::<$ty>()` so that all endian scalar types always use their
wire-format byte size as their FlatBuffer alignment across all target
architectures.
2026-11-06 15:15:33 -08:00
Omar AbdelsalamandDerek Bailey f58d5768f1 Pin swift-crypto for the Swift CI matrix (#9412)
The Swift test job pulls in grpc-swift-2 -> grpc-swift-nio-transport ->
swift-nio-ssl -> swift-crypto, and this package ships no Package.resolved,
so that whole graph is resolved afresh on every run. On 2026-10-15 it
resolved swift-crypto 5.0.1 (released three days earlier) and "Test Swift
Linux (6.2)" turned red before a single line of FlatBuffers' Swift code was
compiled:

  Sources/Crypto/HPKE/Ciphersuite/HPKE-AEAD.swift:27:6: error: unknown
  attribute 'nonexhaustive'

5.x declares swift-tools-version 6.2, which is why only the 6.2 job selects
it; the 6.0 and 6.1 jobs prune it and keep building. The 6.2.x toolchains
then reject the `@nonexhaustive` that 5.x uses, a combination swift-crypto
does not exercise because it builds on nightly.

Restrict the test-only graph to 4.0.0 ..< 4.4.0, which resolves to 4.3.0:
the last 4.x release that declares swift-tools-version 6.0 and so builds
with every toolchain in the matrix. 4.4+ asks for 6.1 and would break the 6.0
job, and the whole 4.x line is free of `@nonexhaustive`.

Co-authored-by: Derek Bailey <derekbailey@google.com>
2026-10-26 10:11:08 -07:00
Derek Bailey 7af1efe4b2 Regenerate monster_test_bfbs_generated.h with alignas(uint64_t) (#9434)
Commit 6dda43bb (#9425) added `alignas(uint64_t)` to embedded binary schemas
generated by `flatc --bfbs-gen-embed`. Regenerate `tests/monster_test_bfbs_generated.h`
via `scripts/generate_code.py` to keep checked-in test artifacts in sync and
unblock CI Check Generated Code.

GitOrigin-RevId: 3786479bebd33365edc91aa13388cdf95d7313d9
2026-10-26 09:06:45 -07:00
Derek Bailey 6dda43bbaa Ensure embedded FlatBuffers binary schemas are 8-byte aligned (#9425)
In `src/idl_gen_cpp.cpp`, code generated by `flatc --bfbs-gen-embed` emits `static const uint8_t bfbsData[...] = { ... };`. Because `uint8_t` has 1-byte alignment, the array may be placed at an unaligned address in `.rodata`, triggering alignment traps under Clang UBSan on Arm when accessed via FlatBuffers root accessors.

Add `alignas(uint64_t)` to the generated `bfbsData` array declaration in `GenerateBinarySchema` so embedded binary schemas are 8-byte aligned across all architectures.

PiperOrigin-RevId: 1003962636
2026-10-21 13:37:51 -07:00
Derek Bailey 9a8a511b52 Enable locale-independent strtod_l/strtof_l on Linux glibc (#9424)
Restrict the `__linux__` check for `FLATBUFFERS_LOCALE_INDEPENDENT` in `include/flatbuffers/base.h` to `(!defined(__linux__) || defined(__GLIBC__))` so Linux with glibc enables `strtod_l`/`strtof_l`.

PiperOrigin-RevId: 1002266254
2026-10-21 13:25:17 -07:00
Wouter van Oortmerssen b8431fbcd7 Lobster: change builder size constants (enum -> let)
This is because newer versions of the Lobster compiler reject enums with the same values, and older compilers are fine with the let versions also.
2026-09-14 11:02:13 -07:00
271 changed files with 24743 additions and 20952 deletions
+13 -13
View File
@@ -42,7 +42,7 @@ jobs:
chmod +x flatc
./flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Linux flatc binary ${{ matrix.cxx }}
path: flatc
@@ -170,7 +170,7 @@ jobs:
- name: test
run: Release\flattests.exe
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Windows flatc binary
path: Release\flatc.exe
@@ -191,7 +191,7 @@ jobs:
build-dotnet-windows:
name: Build .NET Windows
runs-on: windows-2022-64core
runs-on: windows-2022
strategy:
matrix:
configuration: [
@@ -246,7 +246,7 @@ jobs:
chmod +x Release/flatc
Release/flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Mac flatc binary Intel
path: Release/flatc
@@ -289,7 +289,7 @@ jobs:
chmod +x Release/flatc
Release/flatc --version
- name: upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Mac flatc binary Universal
path: Release/flatc
@@ -314,7 +314,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
@@ -373,7 +373,7 @@ jobs:
- name: Run benchmarks
run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}}
- name: Upload benchmarks results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Linux flatbenchmark results ${{matrix.cxx}}
path: benchmarks/results_${{matrix.cxx}}
@@ -394,7 +394,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
@@ -417,7 +417,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- name: set up Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
@@ -446,7 +446,7 @@ jobs:
build-rust-windows:
name: Build Rust Windows
runs-on: windows-2022-64core
runs-on: windows-2022
steps:
- uses: actions/checkout@v6
- name: test
@@ -495,7 +495,7 @@ jobs:
name: Test Swift Linux
strategy:
matrix:
swift: ["5.10", "6.1", "6.2"]
swift: ["6.0", "6.1", "6.2"]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
@@ -534,7 +534,7 @@ jobs:
run: |
swift sdk list
swift build --build-tests --swift-sdk swift-6.2.1-RELEASE_wasm
wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest
wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest --testing-library swift-testing
build-ts:
name: Build TS
@@ -545,7 +545,7 @@ jobs:
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm
run: npm install -g pnpm esbuild
run: npm install -g pnpm@10
- name: deps
run: pnpm i
- name: compile
+2 -2
View File
@@ -21,11 +21,11 @@ jobs:
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
language: c++
fuzz-seconds: 60
- name: Upload Crash
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v3
- uses: actions/setup-node@v6
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
@@ -30,7 +30,7 @@ jobs:
working-directory: ./python
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v4
- uses: actions/setup-python@v6
with:
python-version: '3.10'
+1 -11
View File
@@ -238,15 +238,8 @@ set(FlatBuffers_Tests_SRCS
tests/util_test.cpp
tests/vector_table_naked_ptr_test.h
tests/vector_table_naked_ptr_test.cpp
tests/test_vector_type.h
tests/cpp_vector_type_test.h
tests/cpp_vector_type_test.cpp
tests/native_type_test_impl.h
tests/native_type_test_impl.cpp
tests/bigfoot_ref_test_impl.h
tests/bigfoot_ref_test_impl.cpp
tests/required_table_default_test.h
tests/required_table_default_test.cpp
tests/alignment_test.h
tests/alignment_test.cpp
tests/64bit/offset64_test.h
@@ -555,21 +548,18 @@ if(FLATBUFFERS_BUILD_TESTS)
# The flattest target needs some generated files
SET(FLATC_OPT_COMP --cpp --gen-compare --gen-mutable --gen-object-api --reflect-names)
SET(FLATC_OPT_SCOPED_ENUMS ${FLATC_OPT_COMP};--scoped-enums)
SET(FLATC_OPT_CPP_VECTOR_TYPE ${FLATC_OPT_COMP};--cpp-include;test_vector_type.h;--cpp-vector-type;::flatbuffers::tests::CustomVector)
compile_schema_for_test(tests/alignment_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test_fbsh(tests/default_vectors_strings_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/arrays_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/bigfoot_ref_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/required_table_default_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed")
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/evolution/v2.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/union_underlying_type_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
compile_schema_for_test(tests/cpp_vector_type.fbs "${FLATC_OPT_CPP_VECTOR_TYPE}")
compile_schema_for_test(tests/cross_namespace_pack_test.fbs "${FLATC_OPT_COMP}")
if(FLATBUFFERS_CODE_SANITIZE)
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
+2 -5
View File
@@ -23,7 +23,7 @@ bazel_dep(
)
bazel_dep(
name = "grpc",
version = "1.70.1",
version = "1.76.0",
repo_name = "com_github_grpc_grpc",
)
bazel_dep(
@@ -49,7 +49,7 @@ bazel_dep(
)
bazel_dep(
name = "rules_swift",
version = "2.1.1",
version = "3.1.2",
max_compatibility_level = 3,
repo_name = "build_bazel_rules_swift",
)
@@ -63,9 +63,6 @@ npm.npm_translate_lock(
name = "flatbuffers_npm",
npmrc = "//:.npmrc",
pnpm_lock = "//ts:pnpm-lock.yaml",
# Override the Bazel package where pnpm-lock.yaml is located and link
# to the specified package instead.
root_package = "ts",
verify_node_modules_ignored = "//:.bazelignore",
)
use_repo(npm, "flatbuffers_npm")
+36 -7
View File
@@ -1,4 +1,4 @@
// swift-tools-version:5.10
// swift-tools-version:6.0
/*
* Copyright 2020 Google Inc. All rights reserved.
*
@@ -36,14 +36,17 @@ let package = Package(
.target(
name: "FlatBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlatBuffers"),
path: "swift/Sources/FlatBuffers",
swiftSettings: .settings),
.target(
name: "FlexBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlexBuffers"),
path: "swift/Sources/FlexBuffers",
swiftSettings: .settings),
.target(
name: "Common",
path: "swift/Sources/Common"),
path: "swift/Sources/Common",
swiftSettings: .settings),
.testTarget(
name: "FlatbuffersTests",
dependencies: .dependencies,
@@ -52,7 +55,14 @@ let package = Package(
name: "FlexbuffersTests",
dependencies: ["FlexBuffers"],
path: "tests/swift/Tests/Flexbuffers"),
])
],
swiftLanguageModes: [.v6])
extension Array where Element == SwiftSetting {
static var settings: [SwiftSetting] {
[.enableUpcomingFeature("ExistentialAny")]
}
}
extension Array where Element == Package.Dependency {
static var dependencies: [Package.Dependency] {
@@ -60,7 +70,23 @@ extension Array where Element == Package.Dependency {
[]
#else
// Test only Dependency
[.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.4.1")]
[
.package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.0.0"),
.package(
url: "https://github.com/grpc/grpc-swift-nio-transport.git",
from: "2.0.0"),
// swift-crypto arrives through grpc-swift-nio-transport -> swift-nio-ssl
// and is otherwise resolved afresh on every build, because this package
// ships no Package.resolved. 5.x asks for swift-tools-version 6.2, so only
// the 6.2 CI job selects it - and then fails to compile it, because 5.x
// uses `@nonexhaustive`, which the 6.2.x toolchains do not accept yet.
// Stay on the last 4.x release that still builds with every toolchain in
// the Swift CI matrix (4.3.0 declares swift-tools-version 6.0; 4.4+ asks
// for 6.1 and would drop the 6.0 job).
.package(
url: "https://github.com/apple/swift-crypto.git",
"4.0.0" ..< "4.4.0"),
]
#endif
}
}
@@ -72,7 +98,10 @@ extension Array where Element == PackageDescription.Target.Dependency {
#else
// Test only Dependency
[
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "GRPCCore", package: "grpc-swift-2"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
"FlatBuffers",
]
#endif
@@ -97,6 +97,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
}
benchmark.stopMeasurement()
}
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
@@ -105,6 +106,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.clear())
}
benchmark.stopMeasurement()
}
Benchmark("Strings 10") { benchmark in
@@ -113,6 +115,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10))
}
benchmark.stopMeasurement()
}
Benchmark("Strings 100") { benchmark in
@@ -121,6 +124,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 1 Bytes") { benchmark in
@@ -129,6 +133,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 1 Ints") { benchmark in
@@ -137,6 +142,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 Ints") { benchmark in
@@ -145,6 +151,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 Bytes") { benchmark in
@@ -153,6 +160,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 ContiguousBytes") { benchmark in
@@ -161,6 +169,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}
Benchmark(
@@ -178,6 +187,7 @@ let benchmarks = {
fb.add(offset: off, at: 8)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark(
@@ -190,6 +200,7 @@ let benchmarks = {
let s = fb.startTable(with: 4)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark("Struct") { benchmark in
@@ -198,6 +209,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(struct: array.first!))
}
benchmark.stopMeasurement()
}
Benchmark("Structs") { benchmark in
@@ -219,6 +231,7 @@ let benchmarks = {
fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start))
blackHole(fb.finish(offset: root))
benchmark.stopMeasurement()
}
Benchmark("Vector of Offsets") { benchmark in
@@ -239,12 +252,15 @@ let benchmarks = {
fb.add(offset: off, at: 2)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0))
}
benchmark.stopMeasurement()
}
}
+10
View File
@@ -39,4 +39,14 @@ let package = Package(
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
.executableTarget(
name: "FlexBuffersBenchmarks",
dependencies: [
.product(name: "FlexBuffers", package: "flatbuffers"),
.product(name: "Benchmark", package: "package-benchmark"),
],
path: "Benchmarks/FlexBuffersBenchmarks",
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
])
+2 -1
View File
@@ -5,7 +5,7 @@ import 'types.dart';
/// The main builder class for creation of a FlexBuffer.
class Builder {
final ByteData _buffer;
ByteData _buffer;
List<_StackValue> _stack = [];
List<_StackPointer> _stackPointers = [];
int _offset = 0;
@@ -506,6 +506,7 @@ class Builder {
if (prevSize < size) {
final newBuf = ByteData(size);
newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List());
_buffer = newBuf;
}
return newOffset;
}
+15
View File
@@ -318,6 +318,21 @@ void main() {
1,
]);
}
{
// Default buffer is 2048 bytes, add 2300 bytes of strings that force it
// to grow.
final s1 = 'A' * 1000;
final s2 = 'B' * 800;
final s3 = 'C' * 500;
var flx = Builder()
..startVector()
..addString(s1)
..addString(s2)
..addString(s3)
..end();
expect(flx.finish().length, 2323);
}
});
test('build map', () {
-6
View File
@@ -168,12 +168,6 @@ list of `FILES...`.
std::string from Flatbuffers, but (char* + length). This allows efficient
construction of custom string types, including zero-copy construction.
- `--cpp-vector-type T` : Set object API vector type (default std::vector).
T must be a template taking a single element type argument and support
resize(), reserve(), size(), data(), operator[], emplace_back() and
begin()/end(), matching the subset of std::vector's interface generated
code relies on.
- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
object-based API.
+1 -58
View File
@@ -57,7 +57,7 @@ a `char *` array, which you pass to `GetMonster()`.
```cpp
#include "flatbuffers/flatbuffers.h"
#include "monster_test_generate.h"
#include "monster_test_generated.h"
#include <iostream> // C++ header file for printing
#include <fstream> // C++ header file for file access
@@ -242,42 +242,6 @@ provide the following functions to aide in the serialization process:
}
```
- `bigfoot_ref_wrapper("type")` (on a struct) together with `bigfoot_ref("type")`
(on a field of that struct type): Bigfoot-specific sugar for a
UUID-addressed reference to another native type. `bigfoot_ref_wrapper`
marks a struct as a reference-wrapper template (e.g. Bigfoot's
`HardReference`/`SoftReference`); `bigfoot_ref` on a field of that type
names the referenced native type, e.g. `bigfoot_ref: "::Bigfoot::AssetA"`
on a `HardReference`-typed field with `bigfoot_ref_wrapper:
"::Bigfoot::HardReference"` produces the field's native type
`::Bigfoot::HardReference<::Bigfoot::AssetA>` (auto-deriving a
`native_type_pack_name` of `HardReferenceAssetA`, same short-name
convention as `native_type_pack_name`). Unlike a hand-written
`native_type`, `bigfoot_ref` also emits, directly into the generated
header:
- a forward declaration of the referenced type (so the referencing
schema's generated header never needs that type's real definition -
only the wrapper template's constructor and a `GetUUID()` accessor
are used, and those don't require the referenced type to be
complete), and
- `inline` `Pack<Name>`/`UnPack<Name>` definitions for it (so no
hand-written implementation is required anywhere).
```cpp
struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference") {
uuid: UUID;
}
table AssetB {
ref_a: HardReference (bigfoot_ref: "::Bigfoot::AssetA");
}
```
is enough on its own - no forward declaration of `::Bigfoot::AssetA` and
no `flatbuffers::Pack/UnPackHardReferenceAssetA` implementation need to
be written by hand. `bigfoot_ref` is only valid on fields whose type is a
struct (or vector of structs) that declares `bigfoot_ref_wrapper`.
- `native_type("type")` (on a table): Tables can also be represented with
native types. For example, the following schema:
@@ -373,27 +337,6 @@ constructor in the following format: `custom_str_class(const char *, size_t)`.
Please note that the character array is not guaranteed to be NULL terminated,
you should always use the provided size to determine end of string.
## Using different vector type
By default the object tree's vector fields are built out of `std::vector`,
but you can influence this either globally (using the `--cpp-vector-type`
argument to `flatc`) or per field using the `cpp_vector_type` attribute, to
use any other vector-like template type (e.g. `eastl::vector`).
The type must be a template taking a single element type argument
(`my_vector<T>`), and must support the following member functions:
`resize()`, `reserve()`, `size()`, `data()`, `operator[]`, `emplace_back()`,
and `begin()`/`end()`. This matches the subset of `std::vector`'s interface
that generated code relies on.
Note that unlike `std::vector<bool>`, the custom vector type must not use a
bit-packed specialization for `bool` elements, since generated code accesses
`data()` as a contiguous `bool` array.
As with custom string types, the header defining the custom vector type is
not automatically included; use `--cpp-include` to add the necessary
`#include`.
## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to
+96
View File
@@ -97,6 +97,61 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
*Note: That we never stored a `mana` value, so it will return the default.*
## Fallible API and Custom Allocators
Every `FlatBufferBuilder` method that may allocate has a `try_*` counterpart
(e.g. `try_create_string`, `try_push`, `try_finish`) that returns
`Result<T, A::Error>` instead of panicking. This is useful when allocation
failures must be handled gracefully: for example in `no_std` environments or
with fixed-capacity buffers.
The existing panicking methods are unchanged and remain the simplest option
when using the default allocator.
#### Custom allocators
Implement the `Allocator` trait and pass it to `FlatBufferBuilder::new_in()`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
use flatbuffers::{Allocator, FlatBufferBuilder};
struct MyAllocator { /* ... */ }
unsafe impl Allocator for MyAllocator {
type Error = MyError;
fn grow_downwards(&mut self) -> Result<(), Self::Error> { /* ... */ }
fn len(&self) -> usize { /* ... */ }
}
let alloc = MyAllocator::new(/* ... */);
let mut builder = FlatBufferBuilder::new_in(alloc);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The built-in `DefaultAllocator` uses `Vec<u8>` and sets `Error = Infallible`,
so the `try_*` methods on a default builder can never fail.
#### Example: building a buffer with error propagation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
fn build<A: flatbuffers::Allocator>(
builder: &mut FlatBufferBuilder<A>,
) -> Result<(), A::Error> {
let name = builder.try_create_string("Orc")?;
let inventory = builder.try_create_vector(&[0u8, 1, 2, 3, 4])?;
let table_start = builder.start_table();
builder.try_push_slot_always(Monster::VT_NAME, name)?;
builder.try_push_slot_always(Monster::VT_INVENTORY, inventory)?;
builder.try_push_slot(Monster::VT_HP, 80i16, 100)?;
let root = builder.try_end_table(table_start)?;
builder.try_finish(root, None)?;
Ok(())
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the `FlatBufferBuilder` rustdoc for the full list of `try_*` methods.
## Direct memory access
As you can see from the above examples, all elements in a buffer are
@@ -205,6 +260,47 @@ And example of usage, for the time being, can be found in
- Safe getters in [SafeBuffer](https://docs.rs/flatbuffers-reflection/latest/flatbuffers_reflection/struct.SafeBuffer.html),
which does verification when constructed so you can use it for any data source
## Buffer pre allocation in a latency-sensitive context
In latency-sensitive applications, dynamic memory allocations can introduce unpredictable latency spikes. The `FlatBufferBuilder` internally uses several `Vec`s that may reallocate during serialization:
- The backing buffer for the FlatBuffer data
- `field_locs` for tracking field locations within tables
- `written_vtable_revpos` for deduplicating vtables
- `strings_pool` for shared string interning
To avoid allocations during serialization, you can preallocate all internal vectors upfront using the `with_internal_capacity` constructor:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
// Preallocate: 1KB buffer, 8 field locations, 16 vtables, 32 shared strings
let mut builder = FlatBufferBuilder::with_internal_capacity(1024, 8, 16, 32);
// All subsequent operations will not allocate (if capacities are sufficient)
let name = builder.create_shared_string("MyMonster");
// ... build your FlatBuffer ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are three variants available:
- `with_internal_capacity(size, field_locs, vtables, strings)` - Creates a new builder with all capacities preallocated
- `from_vec_with_internal_capacity(buffer, field_locs, vtables, strings)` - Reuses an existing `Vec<u8>` as the backing buffer
- `new_in_with_internal_capacity(allocator, field_locs, vtables, strings)` - Uses a custom `Allocator` with preallocated internal vecs
When combined with `reset()`, you can reuse the same builder across multiple serializations without any allocations after the initial setup:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
let mut builder = FlatBufferBuilder::with_internal_capacity(1024, 8, 16, 32);
loop {
// Build a FlatBuffer (allocation-free if capacities are sufficient)
let data = build_message(&mut builder);
send(data);
// Reset for reuse - clears state but retains allocated capacity
builder.reset();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Useful tools created by others
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
-3
View File
@@ -427,9 +427,6 @@ Current understood attributes:
it won't be accessible anymore by newer code. Note that if you deprecate a
field that was previous required, old code may fail to validate new data (when
using the optional verifier).
### `required`
- `required` (on a non-scalar table field): this field must always be set. By
default, fields do not need to be present in the binary. This is desirable, as
it helps with forwards/backwards compatibility, and flexibility of data
+1 -1
View File
@@ -26,7 +26,7 @@ Simple mutation | Yes | Yes | Yes | Yes | No | No
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | Yes
Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | Yes | No | No | Yes
Optional Scalars | Yes | Yes | Yes | No | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
Optional Scalars | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | Yes
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
+293 -268
View File
@@ -1,297 +1,322 @@
// automatically generated by the FlatBuffers compiler, do not modify
// @generated
extern crate alloc;
#[allow(unused_imports, dead_code)]
pub mod flatbuffers {
extern crate alloc;
extern crate alloc;
#[allow(unused_imports, dead_code)]
pub mod goldens {
#[allow(unused_imports, dead_code)]
pub mod goldens {
extern crate alloc;
extern crate alloc;
pub enum GalaxyOffset {}
pub enum GalaxyOffset {}
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Galaxy<'a> {
pub _tab: ::flatbuffers::Table<'a>,
}
pub struct Galaxy<'a> {
pub _tab: ::flatbuffers::Table<'a>,
}
impl<'a> ::flatbuffers::Follow<'a> for Galaxy<'a> {
type Inner = Galaxy<'a>;
impl<'a> ::flatbuffers::Follow<'a> for Galaxy<'a> {
type Inner = Galaxy<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
impl<'a> Galaxy<'a> {
pub const VT_NUM_STARS: ::flatbuffers::VOffsetT = 4;
impl<'a> Galaxy<'a> {
pub const VT_NUM_STARS: ::flatbuffers::VOffsetT = 4;
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Galaxy { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args GalaxyArgs
) -> ::flatbuffers::WIPOffset<Galaxy<'bldr>> {
let mut builder = GalaxyBuilder::new(_fbb);
builder.add_num_stars(args.num_stars);
builder.finish()
}
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Galaxy { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args GalaxyArgs
) -> ::flatbuffers::WIPOffset<Galaxy<'bldr>> {
let mut builder = GalaxyBuilder::new(_fbb);
builder.add_num_stars(args.num_stars);
builder.finish()
}
#[inline]
pub fn num_stars(&self) -> i64 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i64>(Galaxy::VT_NUM_STARS, Some(0)).unwrap()}
}
}
#[inline]
pub fn num_stars(&self) -> i64 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i64>(Galaxy::VT_NUM_STARS, Some(0)).unwrap()}
}
}
impl ::flatbuffers::Verifiable for Galaxy<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<i64>("num_stars", Self::VT_NUM_STARS, false)?
.finish();
Ok(())
}
}
pub struct GalaxyArgs {
pub num_stars: i64,
}
impl<'a> Default for GalaxyArgs {
#[inline]
fn default() -> Self {
GalaxyArgs {
num_stars: 0,
}
}
}
impl ::flatbuffers::Verifiable for Galaxy<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<i64>("num_stars", Self::VT_NUM_STARS, false)?
.finish();
Ok(())
}
}
pub struct GalaxyBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GalaxyBuilder<'a, 'b, A> {
#[inline]
pub fn add_num_stars(&mut self, num_stars: i64) {
self.fbb_.push_slot::<i64>(Galaxy::VT_NUM_STARS, num_stars, 0);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> GalaxyBuilder<'a, 'b, A> {
let start = _fbb.start_table();
GalaxyBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Galaxy<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
pub struct GalaxyArgs {
pub num_stars: i64,
}
impl ::core::fmt::Debug for Galaxy<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Galaxy");
ds.field("num_stars", &self.num_stars());
ds.finish()
}
}
pub enum UniverseOffset {}
#[derive(Copy, Clone, PartialEq)]
impl<'a> Default for GalaxyArgs {
#[inline]
fn default() -> Self {
GalaxyArgs {
num_stars: 0,
}
}
}
pub struct Universe<'a> {
pub _tab: ::flatbuffers::Table<'a>,
}
pub struct GalaxyBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a> ::flatbuffers::Follow<'a> for Universe<'a> {
type Inner = Universe<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GalaxyBuilder<'a, 'b, A> {
#[inline]
pub fn add_num_stars(&mut self, num_stars: i64) {
self.fbb_.push_slot::<i64>(Galaxy::VT_NUM_STARS, num_stars, 0);
}
impl<'a> Universe<'a> {
pub const VT_AGE: ::flatbuffers::VOffsetT = 4;
pub const VT_GALAXIES: ::flatbuffers::VOffsetT = 6;
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> GalaxyBuilder<'a, 'b, A> {
let start = _fbb.start_table();
GalaxyBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Universe { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args UniverseArgs<'args>
) -> ::flatbuffers::WIPOffset<Universe<'bldr>> {
let mut builder = UniverseBuilder::new(_fbb);
builder.add_age(args.age);
if let Some(x) = args.galaxies { builder.add_galaxies(x); }
builder.finish()
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Galaxy<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
impl ::core::fmt::Debug for Galaxy<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Galaxy");
ds.field("num_stars", &self.num_stars());
ds.finish()
}
}
pub enum UniverseOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct Universe<'a> {
pub _tab: ::flatbuffers::Table<'a>,
}
impl<'a> ::flatbuffers::Follow<'a> for Universe<'a> {
type Inner = Universe<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
impl<'a> Universe<'a> {
pub const VT_AGE: ::flatbuffers::VOffsetT = 4;
pub const VT_GALAXIES: ::flatbuffers::VOffsetT = 6;
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Universe { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args UniverseArgs<'args>
) -> ::flatbuffers::WIPOffset<Universe<'bldr>> {
let mut builder = UniverseBuilder::new(_fbb);
builder.add_age(args.age);
if let Some(x) = args.galaxies { builder.add_galaxies(x); }
builder.finish()
}
#[inline]
pub fn age(&self) -> f64 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<f64>(Universe::VT_AGE, Some(0.0)).unwrap()}
}
#[inline]
pub fn galaxies(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>> {
// 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<Galaxy>>>>(Universe::VT_GALAXIES, None)}
}
}
#[inline]
pub fn age(&self) -> f64 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<f64>(Universe::VT_AGE, Some(0.0)).unwrap()}
}
impl ::flatbuffers::Verifiable for Universe<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<f64>("age", Self::VT_AGE, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Galaxy>>>>("galaxies", Self::VT_GALAXIES, false)?
.finish();
Ok(())
}
}
pub struct UniverseArgs<'a> {
pub age: f64,
pub galaxies: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>>>,
}
impl<'a> Default for UniverseArgs<'a> {
#[inline]
fn default() -> Self {
UniverseArgs {
age: 0.0,
galaxies: None,
}
}
}
#[inline]
pub fn galaxies(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>> {
// 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<Galaxy>>>>(Universe::VT_GALAXIES, None)}
}
}
pub struct UniverseBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> UniverseBuilder<'a, 'b, A> {
#[inline]
pub fn add_age(&mut self, age: f64) {
self.fbb_.push_slot::<f64>(Universe::VT_AGE, age, 0.0);
}
#[inline]
pub fn add_galaxies(&mut self, galaxies: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset<Galaxy<'b >>>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Universe::VT_GALAXIES, galaxies);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> UniverseBuilder<'a, 'b, A> {
let start = _fbb.start_table();
UniverseBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Universe<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
impl ::flatbuffers::Verifiable for Universe<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<f64>("age", Self::VT_AGE, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Galaxy>>>>("galaxies", Self::VT_GALAXIES, false)?
.finish();
Ok(())
}
}
impl ::core::fmt::Debug for Universe<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Universe");
ds.field("age", &self.age());
ds.field("galaxies", &self.galaxies());
ds.finish()
}
}
#[inline]
/// Verifies that a buffer of bytes contains a `Universe`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
pub fn root_as_universe(buf: &[u8]) -> Result<Universe<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root::<Universe>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `Universe` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_universe_unchecked`.
pub fn size_prefixed_root_as_universe(buf: &[u8]) -> Result<Universe<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root::<Universe>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Universe` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
pub fn root_as_universe_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Universe<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root_with_opts::<Universe<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Universe` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
pub fn size_prefixed_root_as_universe_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Universe<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root_with_opts::<Universe<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Universe and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Universe`.
pub unsafe fn root_as_universe_unchecked(buf: &[u8]) -> Universe<'_> {
unsafe { ::flatbuffers::root_unchecked::<Universe>(buf) }
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Universe and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Universe`.
pub unsafe fn size_prefixed_root_as_universe_unchecked(buf: &[u8]) -> Universe<'_> {
unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Universe>(buf) }
}
#[inline]
pub fn finish_universe_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Universe<'a>>) {
fbb.finish(root, None);
}
pub struct UniverseArgs<'a> {
pub age: f64,
pub galaxies: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>>>,
}
#[inline]
pub fn finish_size_prefixed_universe_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, root: ::flatbuffers::WIPOffset<Universe<'a>>) {
fbb.finish_size_prefixed(root, None);
}
} // pub mod goldens
} // pub mod flatbuffers
impl<'a> Default for UniverseArgs<'a> {
#[inline]
fn default() -> Self {
UniverseArgs {
age: 0.0,
galaxies: None,
}
}
}
pub struct UniverseBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> UniverseBuilder<'a, 'b, A> {
#[inline]
pub fn add_age(&mut self, age: f64) {
self.fbb_.push_slot::<f64>(Universe::VT_AGE, age, 0.0);
}
#[inline]
pub fn add_galaxies(&mut self, galaxies: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset<Galaxy<'b >>>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Universe::VT_GALAXIES, galaxies);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> UniverseBuilder<'a, 'b, A> {
let start = _fbb.start_table();
UniverseBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Universe<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
impl ::core::fmt::Debug for Universe<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Universe");
ds.field("age", &self.age());
ds.field("galaxies", &self.galaxies());
ds.finish()
}
}
/// Verifies that a buffer of bytes contains a `Universe`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
#[inline]
pub fn root_as_universe(buf: &[u8]) -> Result<Universe<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root::<Universe>(buf)
}
/// Verifies that a buffer of bytes contains a size prefixed
/// `Universe` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_universe_unchecked`.
#[inline]
pub fn size_prefixed_root_as_universe(buf: &[u8]) -> Result<Universe<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root::<Universe>(buf)
}
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Universe` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
#[inline]
pub fn root_as_universe_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Universe<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root_with_opts::<Universe<'b>>(opts, buf)
}
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Universe` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_universe_unchecked`.
#[inline]
pub fn size_prefixed_root_as_universe_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Universe<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root_with_opts::<Universe<'b>>(opts, buf)
}
/// Assumes, without verification, that a buffer of bytes contains a Universe and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Universe`.
#[inline]
pub unsafe fn root_as_universe_unchecked(buf: &[u8]) -> Universe<'_> {
unsafe { ::flatbuffers::root_unchecked::<Universe>(buf) }
}
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Universe and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Universe`.
#[inline]
pub unsafe fn size_prefixed_root_as_universe_unchecked(buf: &[u8]) -> Universe<'_> {
unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Universe>(buf) }
}
#[inline]
pub fn finish_universe_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Universe<'a>>
) {
fbb.finish(root, None);
}
#[inline]
pub fn finish_size_prefixed_universe_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Universe<'a>>
) {
fbb.finish_size_prefixed(root, None);
}
} // pub mod goldens
} // pub mod flatbuffers
+1 -1
View File
@@ -4,7 +4,7 @@
import * as flatbuffers from 'flatbuffers';
import { Galaxy } from '../../flatbuffers/goldens/galaxy.js';
import { Galaxy } from './galaxy.js';
export class Universe {
+29 -25
View File
@@ -1,4 +1,4 @@
// swift-tools-version:5.10
// swift-tools-version:6.2
/*
* Copyright 2020 Google Inc. All rights reserved.
*
@@ -20,39 +20,43 @@ import PackageDescription
let package = Package(
name: "Greeter",
platforms: [
.iOS(.v12),
.macOS(.v10_14),
.iOS(.v18),
.macOS(.v15),
],
dependencies: [
.package(path: "../../../../swift"),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0"),
.package(path: "../../../.."),
.package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.0.0"),
.package(
url: "https://github.com/grpc/grpc-swift-nio-transport.git",
from: "2.0.0"),
.package(
url: "https://github.com/apple/swift-argument-parser.git",
from: "1.5.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "Model",
name: "Models",
dependencies: [
"GRPC",
"FlatBuffers",
],
path: "Sources/Model"),
.product(name: "FlatBuffers", package: "flatbuffers"),
.product(name: "GRPCCore", package: "grpc-swift-2"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
]),
// Client for the Greeter example
.target(
name: "Client",
.executableTarget(
name: "Commands",
dependencies: [
"GRPC",
"Model",
],
path: "Sources/client"),
// Server for the Greeter example
.target(
name: "Server",
dependencies: [
"GRPC",
"Model",
],
path: "Sources/server"),
.product(name: "GRPCCore", package: "grpc-swift-2"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
.product(
name: "ArgumentParser",
package: "swift-argument-parser"),
"Models",
]),
])
@@ -1,147 +0,0 @@
// Generated GRPC code for FlatBuffers swift!
/// The following code is generated by the Flatbuffers library which might not be in sync with grpc-swift
/// in case of an issue please open github issue, though it would be maintained
// swiftlint:disable all
// swiftformat:disable all
#if !os(Windows)
import Foundation
import GRPC
import NIO
import NIOHTTP1
import FlatBuffers
public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage {}
public extension GRPCFlatBufPayload {
init(serializedByteBuffer: inout NIO.ByteBuffer) throws {
self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: serializedByteBuffer.readableBytesView, count: serializedByteBuffer.readableBytes))
}
func serialize(into buffer: inout NIO.ByteBuffer) throws {
withUnsafeReadableBytes { buffer.writeBytes($0) }
}
}
extension Message: GRPCFlatBufPayload {}
/// Usage: instantiate models_GreeterServiceClient, then call methods of this protocol to make API calls.
public protocol models_GreeterClientProtocol: GRPCClient {
var serviceName: String { get }
var interceptors: models_GreeterClientInterceptorFactoryProtocol? { get }
func SayHello(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions?
) -> UnaryCall<Message<models_HelloRequest>, Message<models_HelloReply>>
func SayManyHellos(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions?,
handler: @escaping (Message<models_HelloReply>) -> Void
) -> ServerStreamingCall<Message<models_HelloRequest>, Message<models_HelloReply>>
}
extension models_GreeterClientProtocol {
public var serviceName: String { "models.Greeter" }
public func SayHello(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions? = nil
) -> UnaryCall<Message<models_HelloRequest>, Message<models_HelloReply>> {
return self.makeUnaryCall(
path: "/models.Greeter/SayHello",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSayHelloInterceptors() ?? []
)
}
public func SayManyHellos(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions? = nil,
handler: @escaping (Message<models_HelloReply>) -> Void
) -> ServerStreamingCall<Message<models_HelloRequest>, Message<models_HelloReply>> {
return self.makeServerStreamingCall(
path: "/models.Greeter/SayManyHellos",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSayManyHellosInterceptors() ?? [],
handler: handler
)
}
}
public protocol models_GreeterClientInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when invoking 'SayHello'.
func makeSayHelloInterceptors() -> [ClientInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
/// - Returns: Interceptors to use when invoking 'SayManyHellos'.
func makeSayManyHellosInterceptors() -> [ClientInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
}
public final class models_GreeterServiceClient: models_GreeterClientProtocol {
public let channel: GRPCChannel
public var defaultCallOptions: CallOptions
public var interceptors: models_GreeterClientInterceptorFactoryProtocol?
public init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: models_GreeterClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
}
}
public protocol models_GreeterProvider: CallHandlerProvider {
var interceptors: models_GreeterServerInterceptorFactoryProtocol? { get }
func SayHello(request: Message<models_HelloRequest>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<models_HelloReply>>
func SayManyHellos(request: Message<models_HelloRequest>, context: StreamingResponseCallContext<Message<models_HelloReply>>) -> EventLoopFuture<GRPCStatus>
}
public extension models_GreeterProvider {
var serviceName: Substring { return "models.Greeter" }
func handle(method name: Substring, context: CallHandlerContext) -> GRPCServerHandlerProtocol? {
switch name {
case "SayHello":
return UnaryServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<models_HelloRequest>>(),
responseSerializer: GRPCPayloadSerializer<Message<models_HelloReply>>(),
interceptors: self.interceptors?.makeSayHelloInterceptors() ?? [],
userFunction: self.SayHello(request:context:))
case "SayManyHellos":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<models_HelloRequest>>(),
responseSerializer: GRPCPayloadSerializer<Message<models_HelloReply>>(),
interceptors: self.interceptors?.makeSayManyHellosInterceptors() ?? [],
userFunction: self.SayManyHellos(request:context:))
default: return nil;
}
}
}
public protocol models_GreeterServerInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when handling 'SayHello'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSayHelloInterceptors() -> [ServerInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
/// - Returns: Interceptors to use when handling 'SayManyHellos'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSayManyHellosInterceptors() -> [ServerInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
}
#endif
@@ -1,104 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
// swiftlint:disable all
// swiftformat:disable all
#if canImport(Common)
import Common
#endif
import FlatBuffers
public struct models_HelloReply: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private enum VTOFFSET: VOffset {
case message = 4
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
}
public var message: String? { let o = _accessor.offset(VTOFFSET.message.v); return o == 0 ? nil : _accessor.string(at: o) }
public var messageSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.message.v) }
public static func startHelloReply(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
public static func add(message: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: message, at: VTOFFSET.message.p) }
public static func endHelloReply(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createHelloReply(
_ fbb: inout FlatBufferBuilder,
messageOffset message: Offset = Offset()
) -> Offset {
let __start = models_HelloReply.startHelloReply(&fbb)
models_HelloReply.add(message: message, &fbb)
return models_HelloReply.endHelloReply(&fbb, start: __start)
}
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
var _v = try verifier.visitTable(at: position)
try _v.visit(field: VTOFFSET.message.p, fieldName: "message", required: false, type: ForwardOffset<String>.self)
_v.finish()
}
}
extension models_HelloReply: Encodable {
enum CodingKeys: String, CodingKey {
case message = "message"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(message, forKey: .message)
}
}
public struct models_HelloRequest: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private enum VTOFFSET: VOffset {
case name = 4
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
}
public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) }
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
public static func startHelloRequest(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
public static func endHelloRequest(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createHelloRequest(
_ fbb: inout FlatBufferBuilder,
nameOffset name: Offset = Offset()
) -> Offset {
let __start = models_HelloRequest.startHelloRequest(&fbb)
models_HelloRequest.add(name: name, &fbb)
return models_HelloRequest.endHelloRequest(&fbb, start: __start)
}
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
var _v = try verifier.visitTable(at: position)
try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
_v.finish()
}
}
extension models_HelloRequest: Encodable {
enum CodingKeys: String, CodingKey {
case name = "name"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(name, forKey: .name)
}
}
@@ -1,108 +0,0 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import FlatBuffers
import GRPC
import Logging
import Model
import NIO
// Quieten the logs.
LoggingSystem.bootstrap {
var handler = StreamLogHandler.standardOutput(label: $0)
handler.logLevel = .critical
return handler
}
func greet(name: String, client greeter: models_GreeterServiceClient) {
// Form the request with the name, if one was provided.
var builder = FlatBufferBuilder()
let nameOff = builder.create(string: name)
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: nameOff)
builder.finish(offset: root)
// Make the RPC call to the server.
let sayHello =
greeter
.SayHello(Message<models_HelloRequest>(builder: &builder))
// wait() on the response to stop the program from exiting before the response is received.
do {
let response = try sayHello.response.wait()
print("Greeter SayHello received: \(response.object.message ?? "Unknown")")
} catch {
print("Greeter failed: \(error)")
}
let surname = builder.create(string: name)
let manyRoot = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: surname)
builder.finish(offset: manyRoot)
let call = greeter.SayManyHellos(Message(builder: &builder)) { message in
print(
"Greeter SayManyHellos received: \(message.object.message ?? "Unknown")")
}
let status = try! call.status.recover { _ in .processingError }.wait()
if status.code != .ok {
print("RPC failed: \(status)")
}
}
func main(args: [String]) {
// arg0 (dropped) is the program name. We expect arg1 to be the port, and arg2 (optional) to be
// the name sent in the request.
let arg1 = args.dropFirst(1).first
let arg2 = args.dropFirst(2).first
switch (arg1.flatMap(Int.init), arg2) {
case (.none, _):
print("Usage: PORT [NAME]")
exit(1)
case (.some(let port), let name):
// Setup an `EventLoopGroup` for the connection to run on.
//
// See: https://github.com/apple/swift-nio#eventloops-and-eventloopgroups
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
// Make sure the group is shutdown when we're done with it.
defer {
try! group.syncShutdownGracefully()
}
// Configure the channel, we're not using TLS so the connection is `insecure`.
let channel = ClientConnection.insecure(group: group)
.connect(host: "localhost", port: port)
// Close the connection when we're done with it.
defer {
try! channel.close().wait()
}
// Provide the connection to the generated client.
let greeter = models_GreeterServiceClient(channel: channel)
// Do the greeting.
greet(name: name ?? "FlatBuffers!", client: greeter)
}
}
main(args: CommandLine.arguments)
@@ -1,97 +0,0 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import FlatBuffers
import GRPC
import Logging
import Model
import NIO
class Greeter: models_GreeterProvider {
var interceptors: models_GreeterServerInterceptorFactoryProtocol?
let greetings: [String]
init() {
greetings = ["Hi", "Hallo", "Ciao"]
}
func SayHello(
request: Message<models_HelloRequest>,
context: StatusOnlyCallContext)
-> EventLoopFuture<Message<models_HelloReply>>
{
let recipient = request.object.name ?? "Stranger"
var builder = FlatBufferBuilder()
let off = builder.create(string: "Hello \(recipient)")
let root = models_HelloReply.createHelloReply(&builder, messageOffset: off)
builder.finish(offset: root)
return context.eventLoop
.makeSucceededFuture(Message<models_HelloReply>(builder: &builder))
}
func SayManyHellos(
request: Message<models_HelloRequest>,
context: StreamingResponseCallContext<Message<models_HelloReply>>)
-> EventLoopFuture<GRPCStatus>
{
for name in greetings {
var builder = FlatBufferBuilder()
let off =
builder
.create(string: "\(name) \(request.object.name ?? "Unknown")")
let root = models_HelloReply.createHelloReply(
&builder,
messageOffset: off)
builder.finish(offset: root)
_ = context.sendResponse(Message<models_HelloReply>(builder: &builder))
}
return context.eventLoop.makeSucceededFuture(.ok)
}
}
// Quieten the logs.
LoggingSystem.bootstrap {
var handler = StreamLogHandler.standardOutput(label: $0)
handler.logLevel = .critical
return handler
}
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
// Create some configuration for the server:
let configuration = Server.Configuration(
target: .hostAndPort("localhost", 0),
eventLoopGroup: group,
serviceProviders: [Greeter()])
// Start the server and print its address once it has started.
let server = Server.start(configuration: configuration)
server.map {
$0.channel.localAddress
}.whenSuccess { address in
print("server started on port \(address!.port!)")
}
// Wait on the server's `onClose` future to stop the program from exiting.
_ = try server.flatMap {
$0.onClose
}.wait()
+14 -5
View File
@@ -172,6 +172,7 @@ class StubGenerator : public BaseGenerator {
<< " def __init__(self, channel: grpc.Channel) -> None: ...\n";
for (const RPCCall* method : service->calls.vec) {
imports->Import("typing");
std::string request = "bytes";
std::string response = "bytes";
@@ -183,14 +184,22 @@ class StubGenerator : public BaseGenerator {
imports->Import(ModuleFor(method->response), response);
}
ss << " def " << method->name << "(self, ";
ss << " def " << method->name << "(\n";
ss << " self,\n";
if (ClientStreaming(method)) {
imports->Import("typing");
ss << "request_iterator: typing.Iterator[" << request << "]";
ss << " request_iterator: typing.Iterator[" << request << "]\n";
} else {
ss << "request: " << request;
ss << " request: " << request << ",\n";
}
ss << ") -> ";
ss << " timeout: float | None = None,\n";
// https://github.com/python/typeshed/blob/ccf9411fb1f5bee2a8e3d278889de17a08f7bbe3/stubs/grpcio/grpc/__init__.pyi#L37
ss << " metadata: typing.Sequence[tuple[str, typing.Union[str, bytes]]] | None = None,\n";
ss << " credentials: grpc.CallCredentials | None = None,\n";
ss << " wait_for_ready: bool | None = None,\n";
ss << " compression: grpc.Compression | None = None\n";
ss << " ) -> ";
if (ServerStreaming(method)) {
imports->Import("typing");
ss << "typing.Iterator[" << response << "]";
File diff suppressed because it is too large Load Diff
+1 -14
View File
@@ -142,19 +142,6 @@
#define FLATBUFFERS_VERSION_MAJOR 25
#define FLATBUFFERS_VERSION_MINOR 12
#define FLATBUFFERS_VERSION_REVISION 19
// Identifies this header as Bigfoot's fork of flatbuffers, and versions the
// fork's own generated-code-affecting changes independently of the upstream
// FLATBUFFERS_VERSION_* triplet above (which just tracks the upstream
// version this fork is based on, and would still match an unforked, stock
// flatbuffers install of the same version). Generated headers assert on
// this - see GenFlatbuffersVersionCheck() in idl_gen_cpp.cpp - so building
// Bigfoot-generated code against stock flatbuffers, or a differently
// versioned Bigfoot fork, fails to compile immediately instead of silently
// miscompiling. Bump this whenever a change here affects what generated
// code assumes about this header (e.g. adding bigfoot_ref/bigfoot_ref_wrapper).
#define FLATBUFFERS_BIGFOOT_VERSION 1
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {
@@ -284,7 +271,7 @@ namespace flatbuffers {
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || \
(defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__>= 26) || \
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
!defined(__Fuchsia__)
!defined(__Fuchsia__) && (!defined(__linux__) || defined(__GLIBC__))
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
#else
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
+18 -4
View File
@@ -1207,11 +1207,20 @@ class Builder FLATBUFFERS_FINAL_CLASS {
String(str);
}
size_t AlignedBlob(const void* data, size_t len, BitWidth alignment) {
// The requested alignment must not be smaller than the one required to
// store the length.
return CreateAlignedBlob(data, len, 0, FBT_BLOB,
std::max(alignment, WidthU(len)));
}
size_t AlignedBlob(const std::vector<uint8_t>& v, BitWidth alignment) {
return AlignedBlob(v.data(), v.size(), alignment);
}
size_t Blob(const void* data, size_t len) {
return CreateBlob(data, len, 0, FBT_BLOB);
}
size_t Blob(const std::vector<uint8_t>& v) {
return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
return Blob(v.data(), v.size());
}
void Blob(const char* key, const void* data, size_t len) {
@@ -1693,11 +1702,16 @@ class Builder FLATBUFFERS_FINAL_CLASS {
size_t CreateBlob(const void* data, size_t len, size_t trailing, Type type) {
auto bit_width = WidthU(len);
auto byte_width = Align(bit_width);
return CreateAlignedBlob(data, len, trailing, type, bit_width);
}
size_t CreateAlignedBlob(const void* data, size_t len, size_t trailing,
Type type, BitWidth alignment) {
auto byte_width = Align(alignment);
Write<uint64_t>(len, byte_width);
auto sloc = buf_.size();
WriteBytes(data, len + trailing);
stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
stack_.push_back(Value(static_cast<uint64_t>(sloc), type, alignment));
return sloc;
}
@@ -1962,7 +1976,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool VerifyKey(const uint8_t* p) {
FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
while (p < buf_ + size_)
if (*p++) return true;
if (!*p++) return true;
return false;
}
-4
View File
@@ -677,7 +677,6 @@ struct IDLOptions {
std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type;
bool cpp_object_api_string_flexible_constructor;
std::string cpp_object_api_vector_type;
CaseStyle cpp_object_api_field_case_style;
bool cpp_direct_copy;
bool gen_nullable;
@@ -1013,13 +1012,10 @@ class Parser : public ParserState {
known_attributes_["cpp_ptr_type_get"] = true;
known_attributes_["cpp_str_type"] = true;
known_attributes_["cpp_str_flex_ctor"] = true;
known_attributes_["cpp_vector_type"] = true;
known_attributes_["native_inline"] = true;
known_attributes_["native_custom_alloc"] = true;
known_attributes_["native_type"] = true;
known_attributes_["native_type_pack_name"] = true;
known_attributes_["bigfoot_ref_wrapper"] = true;
known_attributes_["bigfoot_ref"] = true;
known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true;
known_attributes_["private"] = true;
+37 -35
View File
@@ -30,50 +30,52 @@ namespace flatbuffers {
// ------------------------- GETTERS -------------------------
inline bool IsScalar(reflection::BaseType t) {
constexpr bool IsScalar(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::Double;
}
inline bool IsInteger(reflection::BaseType t) {
constexpr bool IsInteger(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::ULong;
}
inline bool IsFloat(reflection::BaseType t) {
constexpr bool IsFloat(reflection::BaseType t) {
return t == reflection::Float || t == reflection::Double;
}
inline bool IsLong(reflection::BaseType t) {
constexpr bool IsLong(reflection::BaseType t) {
return t == reflection::Long || t == reflection::ULong;
}
// Size of a basic type, don't use with structs.
inline size_t GetTypeSize(reflection::BaseType base_type) {
// This needs to correspond to the BaseType enum.
static size_t sizes[] = {
0, // None
1, // UType
1, // Bool
1, // Byte
1, // UByte
2, // Short
2, // UShort
4, // Int
4, // UInt
8, // Long
8, // ULong
4, // Float
8, // Double
4, // String
4, // Vector
4, // Obj
4, // Union
0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
// errors.
8, // Vector64
// This needs to correspond to the BaseType enum.
constexpr size_t kBaseTypeSize[] = {
0, // None
1, // UType
1, // Bool
1, // Byte
1, // UByte
2, // Short
2, // UShort
4, // Int
4, // UInt
8, // Long
8, // ULong
4, // Float
8, // Double
4, // String
4, // Vector
4, // Obj
4, // Union
0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
// errors.
8, // Vector64
0 // MaxBaseType. This must be kept the last entry in this array.
};
static_assert(sizeof(sizes) / sizeof(size_t) == reflection::MaxBaseType + 1,
"Size of sizes[] array does not match the count of BaseType "
"enum values.");
return sizes[base_type];
0 // MaxBaseType. This must be kept the last entry in this array.
};
static_assert(sizeof(kBaseTypeSize) / sizeof(size_t) ==
reflection::MaxBaseType + 1,
"Size of sizes[] array does not match the count of BaseType "
"enum values.");
// Size of a basic type, don't use with structs.
constexpr size_t GetTypeSize(reflection::BaseType base_type) {
return kBaseTypeSize[base_type];
}
// Same as above, but now correctly returns the size of a struct if
@@ -420,7 +422,7 @@ pointer_inside_vector<T, U> piv(T* ptr, std::vector<U>& vec) {
return pointer_inside_vector<T, U>(ptr, vec);
}
inline const char* UnionTypeFieldSuffix() { return "_type"; }
constexpr const char* UnionTypeFieldSuffix() { return "_type"; }
// Helper to figure out the actual table type a union refers to.
inline const reflection::Object& GetUnionType(
+8 -9
View File
@@ -24,15 +24,14 @@ class handle:
struct offset:
o:int
enum sizeof:
sz_8 = 1
sz_16 = 2
sz_32 = 4
sz_64 = 8
sz_voffset = 2
sz_uoffset = 4
sz_soffset = 4
sz_metadata_fields = 2
let sz_8 = 1
let sz_16 = 2
let sz_32 = 4
let sz_64 = 8
let sz_voffset = 2
let sz_uoffset = 4
let sz_soffset = 4
let sz_metadata_fields = 2
class builder:
buf = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+1 -2
View File
@@ -438,8 +438,7 @@ namespace Google.FlatBuffers
if (off > Offset)
throw new ArgumentException();
if (off != 0)
off = Offset - off + sizeof(int);
off = Offset - off + sizeof(int);
PutInt(off);
}
+1 -5
View File
@@ -65,11 +65,7 @@ namespace Google.FlatBuffers
// Create a .NET String from UTF-8 data stored inside the flatbuffer.
public string __string(int offset)
{
int stringOffset = bb.GetInt(offset);
if (stringOffset == 0)
return null;
offset += stringOffset;
offset += bb.GetInt(offset);
var len = bb.GetInt(offset);
var startPos = offset + sizeof(int);
return bb.GetStringUTF8(startPos, len);
+25 -19
View File
@@ -33,6 +33,12 @@ importers:
specifier: ^8.34.1
version: 8.34.1(eslint@9.29.0)(typescript@5.8.3)
tests/ts:
dependencies:
flatbuffers:
specifier: workspace:*
version: link:../..
packages:
'@esbuild/aix-ppc64@0.25.5':
@@ -343,8 +349,8 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
ajv@6.14.0:
resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@@ -483,8 +489,8 @@ packages:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'}
flatted@3.3.1:
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
flatted@3.4.2:
resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@@ -571,11 +577,11 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@3.1.5:
resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
minimatch@9.0.9:
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
engines: {node: '>=16 || 14 >=14.17'}
ms@2.1.3:
@@ -793,7 +799,7 @@ snapshots:
dependencies:
'@eslint/object-schema': 2.1.6
debug: 4.3.7
minimatch: 3.1.2
minimatch: 3.1.5
transitivePeerDependencies:
- supports-color
@@ -809,14 +815,14 @@ snapshots:
'@eslint/eslintrc@3.3.1':
dependencies:
ajv: 6.12.6
ajv: 6.14.0
debug: 4.3.7
espree: 10.4.0
globals: 14.0.0
ignore: 5.3.2
import-fresh: 3.3.0
js-yaml: 4.1.1
minimatch: 3.1.2
minimatch: 3.1.5
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
@@ -932,7 +938,7 @@ snapshots:
debug: 4.3.7
fast-glob: 3.3.2
is-glob: 4.0.3
minimatch: 9.0.5
minimatch: 9.0.9
semver: 7.6.3
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
@@ -961,7 +967,7 @@ snapshots:
acorn@8.15.0: {}
ajv@6.12.6:
ajv@6.14.0:
dependencies:
fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0
@@ -1070,7 +1076,7 @@ snapshots:
'@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8
'@types/json-schema': 7.0.15
ajv: 6.12.6
ajv: 6.14.0
chalk: 4.1.2
cross-spawn: 7.0.6
debug: 4.3.7
@@ -1089,7 +1095,7 @@ snapshots:
is-glob: 4.0.3
json-stable-stringify-without-jsonify: 1.0.1
lodash.merge: 4.6.2
minimatch: 3.1.2
minimatch: 3.1.5
natural-compare: 1.4.0
optionator: 0.9.4
transitivePeerDependencies:
@@ -1146,10 +1152,10 @@ snapshots:
flat-cache@4.0.1:
dependencies:
flatted: 3.3.1
flatted: 3.4.2
keyv: 4.5.4
flatted@3.3.1: {}
flatted@3.4.2: {}
glob-parent@5.1.2:
dependencies:
@@ -1218,11 +1224,11 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
minimatch@3.1.2:
minimatch@3.1.5:
dependencies:
brace-expansion: 1.1.12
minimatch@9.0.5:
minimatch@9.0.9:
dependencies:
brace-expansion: 2.0.2
+3 -3
View File
@@ -159,7 +159,7 @@ def EnumCreateValuesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateValuesVector(builder, data):
EnumCreateValuesVector(builder, data)
return EnumCreateValuesVector(builder, data)
def EnumAddIsUnion(builder, isUnion):
builder.PrependBoolSlot(2, isUnion, 0)
@@ -189,7 +189,7 @@ def EnumCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
EnumCreateAttributesVector(builder, data)
return EnumCreateAttributesVector(builder, data)
def EnumAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -207,7 +207,7 @@ def EnumCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
EnumCreateDocumentationVector(builder, data)
return EnumCreateDocumentationVector(builder, data)
def EnumAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0)
+2 -2
View File
@@ -138,7 +138,7 @@ def EnumValCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
EnumValCreateDocumentationVector(builder, data)
return EnumValCreateDocumentationVector(builder, data)
def EnumValAddAttributes(builder, attributes):
builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
@@ -156,7 +156,7 @@ def EnumValCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
EnumValCreateAttributesVector(builder, data)
return EnumValCreateAttributesVector(builder, data)
def EnumValEnd(builder):
return builder.EndObject()
+2 -2
View File
@@ -239,7 +239,7 @@ def FieldCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
FieldCreateAttributesVector(builder, data)
return FieldCreateAttributesVector(builder, data)
def FieldAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(10, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -257,7 +257,7 @@ def FieldCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
FieldCreateDocumentationVector(builder, data)
return FieldCreateDocumentationVector(builder, data)
def FieldAddOptional(builder, optional):
builder.PrependBoolSlot(11, optional, 0)
+3 -3
View File
@@ -162,7 +162,7 @@ def ObjectCreateFieldsVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateFieldsVector(builder, data):
ObjectCreateFieldsVector(builder, data)
return ObjectCreateFieldsVector(builder, data)
def ObjectAddIsStruct(builder, isStruct):
builder.PrependBoolSlot(2, isStruct, 0)
@@ -198,7 +198,7 @@ def ObjectCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
ObjectCreateAttributesVector(builder, data)
return ObjectCreateAttributesVector(builder, data)
def ObjectAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -216,7 +216,7 @@ def ObjectCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
ObjectCreateDocumentationVector(builder, data)
return ObjectCreateDocumentationVector(builder, data)
def ObjectAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(7, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0)
+2 -2
View File
@@ -142,7 +142,7 @@ def RPCCallCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
RPCCallCreateAttributesVector(builder, data)
return RPCCallCreateAttributesVector(builder, data)
def RPCCallAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -160,7 +160,7 @@ def RPCCallCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
RPCCallCreateDocumentationVector(builder, data)
return RPCCallCreateDocumentationVector(builder, data)
def RPCCallEnd(builder):
return builder.EndObject()
+4 -4
View File
@@ -184,7 +184,7 @@ def SchemaCreateObjectsVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateObjectsVector(builder, data):
SchemaCreateObjectsVector(builder, data)
return SchemaCreateObjectsVector(builder, data)
def SchemaAddEnums(builder, enums):
builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(enums), 0)
@@ -202,7 +202,7 @@ def SchemaCreateEnumsVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateEnumsVector(builder, data):
SchemaCreateEnumsVector(builder, data)
return SchemaCreateEnumsVector(builder, data)
def SchemaAddFileIdent(builder, fileIdent):
builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(fileIdent), 0)
@@ -238,7 +238,7 @@ def SchemaCreateServicesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateServicesVector(builder, data):
SchemaCreateServicesVector(builder, data)
return SchemaCreateServicesVector(builder, data)
def SchemaAddAdvancedFeatures(builder, advancedFeatures):
builder.PrependUint64Slot(6, advancedFeatures, 0)
@@ -262,7 +262,7 @@ def SchemaCreateFbsFilesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateFbsFilesVector(builder, data):
SchemaCreateFbsFilesVector(builder, data)
return SchemaCreateFbsFilesVector(builder, data)
def SchemaEnd(builder):
return builder.EndObject()
+1 -1
View File
@@ -88,7 +88,7 @@ def SchemaFileCreateIncludedFilenamesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateIncludedFilenamesVector(builder, data):
SchemaFileCreateIncludedFilenamesVector(builder, data)
return SchemaFileCreateIncludedFilenamesVector(builder, data)
def SchemaFileEnd(builder):
return builder.EndObject()
+3 -3
View File
@@ -141,7 +141,7 @@ def ServiceCreateCallsVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateCallsVector(builder, data):
ServiceCreateCallsVector(builder, data)
return ServiceCreateCallsVector(builder, data)
def ServiceAddAttributes(builder, attributes):
builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
@@ -159,7 +159,7 @@ def ServiceCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data):
ServiceCreateAttributesVector(builder, data)
return ServiceCreateAttributesVector(builder, data)
def ServiceAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -177,7 +177,7 @@ def ServiceCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data):
ServiceCreateDocumentationVector(builder, data)
return ServiceCreateDocumentationVector(builder, data)
def ServiceAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0)
+1 -5
View File
@@ -1,6 +1,2 @@
[bdist_wheel]
universal=1
[metadata]
license_files =
../LICENSE
license_files = LICENSE
+49 -30
View File
@@ -12,35 +12,54 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from pathlib import Path
import shutil
from setuptools import setup
setup(
name='flatbuffers',
version='25.12.19',
license='Apache 2.0',
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/>`_ '
'serialization format.'
),
packages=['flatbuffers'],
include_package_data=True,
requires=[],
description='The FlatBuffers serialization format for Python',
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
],
project_urls={
'Documentation': 'https://google.github.io/flatbuffers/',
'Source': 'https://github.com/google/flatbuffers',
},
)
_THIS_DIR = Path(__file__).resolve().parent
_ROOT_LICENSE = _THIS_DIR.parent / 'LICENSE'
_LOCAL_LICENSE = _THIS_DIR / 'LICENSE'
def _stage_license_file():
if _LOCAL_LICENSE.exists() or not _ROOT_LICENSE.exists():
return False
shutil.copyfile(_ROOT_LICENSE, _LOCAL_LICENSE)
return True
_remove_staged_license = _stage_license_file()
try:
setup(
name='flatbuffers',
version='25.12.19',
license='Apache 2.0',
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/>`_ '
'serialization format.'
),
packages=['flatbuffers'],
include_package_data=True,
requires=[],
description='The FlatBuffers serialization format for Python',
classifiers=[
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
],
project_urls={
'Documentation': 'https://google.github.io/flatbuffers/',
'Source': 'https://github.com/google/flatbuffers',
},
)
finally:
if _remove_staged_license and _LOCAL_LICENSE.exists():
_LOCAL_LICENSE.unlink()
+578 -109
View File
@@ -24,6 +24,9 @@ use core::marker::PhantomData;
use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, Sub, SubAssign};
use core::ptr::write_bytes;
#[cfg(feature = "std")]
use std::collections::HashMap;
use crate::endian_scalar::emplace_scalar;
use crate::primitives::*;
use crate::push::{Push, PushAlignment};
@@ -139,6 +142,9 @@ pub struct FlatBufferBuilder<'fbb, A: Allocator = DefaultAllocator> {
min_align: usize,
force_defaults: bool,
#[cfg(feature = "std")]
strings_pool: HashMap<String, WIPOffset<&'fbb str>>,
#[cfg(not(feature = "std"))]
strings_pool: Vec<WIPOffset<&'fbb str>>,
_phantom: PhantomData<&'fbb ()>,
@@ -160,6 +166,60 @@ impl<'fbb> FlatBufferBuilder<'fbb, DefaultAllocator> {
pub fn with_capacity(size: usize) -> Self {
Self::from_vec(vec![0; size])
}
/// Create a FlatBufferBuilder that is ready for writing, with a
/// ready-to-use capacity of the provided size and preallocated internal vecs.
///
/// The maximum valid value for `size` is `FLATBUFFERS_MAX_BUFFER_SIZE`.
///
/// # Arguments
///
/// * `size` - The initial capacity of the backing buffer in bytes.
/// * `field_locs_capacity` - Preallocated capacity for the field locations vec.
/// * `written_vtable_revpos_capacity` - Preallocated capacity for the written vtable reverse positions vec.
/// * `strings_pool_capacity` - Preallocated capacity for the shared strings pool vec.
pub fn with_internal_capacity(
size: usize,
field_locs_capacity: usize,
written_vtable_revpos_capacity: usize,
strings_pool_capacity: usize,
) -> Self {
Self::from_vec_with_internal_capacity(
vec![0; size],
field_locs_capacity,
written_vtable_revpos_capacity,
strings_pool_capacity,
)
}
/// Create a FlatBufferBuilder that is ready for writing, reusing
/// an existing vector and preallocated internal vecs.
///
/// # Arguments
///
/// * `buffer` - An existing `Vec<u8>` to reuse as the backing buffer.
/// * `field_locs_capacity` - Preallocated capacity for the field locations vec.
/// * `written_vtable_revpos_capacity` - Preallocated capacity for the written vtable reverse positions vec.
/// * `strings_pool_capacity` - Preallocated capacity for the shared strings pool vec.
pub fn from_vec_with_internal_capacity(
buffer: Vec<u8>,
field_locs_capacity: usize,
written_vtable_revpos_capacity: usize,
strings_pool_capacity: usize,
) -> Self {
// we need to check the size here because we create the backing buffer
// directly, bypassing the typical way of using grow_allocator:
assert!(
buffer.len() <= FLATBUFFERS_MAX_BUFFER_SIZE,
"cannot initialize buffer bigger than 2 gigabytes"
);
let allocator = DefaultAllocator::from_vec(buffer);
Self::new_in_with_internal_capacity(
allocator,
field_locs_capacity,
written_vtable_revpos_capacity,
strings_pool_capacity,
)
}
/// Create a FlatBufferBuilder that is ready for writing, reusing
/// an existing vector.
pub fn from_vec(buffer: Vec<u8>) -> Self {
@@ -197,12 +257,52 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
min_align: 0,
force_defaults: false,
#[cfg(feature = "std")]
strings_pool: HashMap::new(),
#[cfg(not(feature = "std"))]
strings_pool: Vec::new(),
_phantom: PhantomData,
}
}
/// Create a [`FlatBufferBuilder`] that is ready for writing with a custom [`Allocator`]
/// and preallocated internal vecs.
///
/// # Arguments
///
/// * `allocator` - A custom [`Allocator`] to use as the backing buffer.
/// * `field_locs_capacity` - Preallocated capacity for the field locations vec.
/// * `written_vtable_revpos_capacity` - Preallocated capacity for the written vtable reverse positions vec.
/// * `strings_pool_capacity` - Preallocated capacity for the shared strings pool vec.
pub fn new_in_with_internal_capacity(
allocator: A,
field_locs_capacity: usize,
written_vtable_revpos_capacity: usize,
strings_pool_capacity: usize,
) -> Self {
let head = ReverseIndex::end();
FlatBufferBuilder {
allocator,
head,
field_locs: Vec::with_capacity(field_locs_capacity),
written_vtable_revpos: Vec::with_capacity(written_vtable_revpos_capacity),
nested: false,
finished: false,
min_align: 0,
force_defaults: false,
#[cfg(feature = "std")]
strings_pool: HashMap::with_capacity(strings_pool_capacity),
#[cfg(not(feature = "std"))]
strings_pool: Vec::with_capacity(strings_pool_capacity),
_phantom: PhantomData,
}
}
/// Destroy the [`FlatBufferBuilder`], returning its [`Allocator`] and the index
/// into it that represents the start of valid data.
pub fn collapse_in(self) -> (A, usize) {
@@ -223,7 +323,9 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// new object.
pub fn reset(&mut self) {
// memset only the part of the buffer that could be dirty:
self.allocator[self.head.range_to_end()].iter_mut().for_each(|x| *x = 0);
self.allocator[self.head.range_to_end()]
.iter_mut()
.for_each(|x| *x = 0);
self.head = ReverseIndex::end();
self.written_vtable_revpos.clear();
@@ -235,22 +337,43 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.strings_pool.clear();
}
/// Push a Push'able value onto the front of the in-progress data.
///
/// This function uses traits to provide a unified API for writing
/// scalars, tables, vectors, and WIPOffsets.
/// Fallible version of [`push`](Self::push).
#[inline]
pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> {
pub fn try_push<P: Push>(&mut self, x: P) -> Result<WIPOffset<P::Output>, A::Error> {
let sz = P::size();
self.align(sz, P::alignment());
self.make_space(sz);
self.align(sz, P::alignment())?;
self.make_space(sz)?;
{
let (dst, rest) = self.allocator[self.head.range_to_end()].split_at_mut(sz);
// Safety:
// Called make_space above
unsafe { x.push(dst, rest.len()) };
}
WIPOffset::new(self.used_space() as UOffsetT)
Ok(WIPOffset::new(self.used_space() as UOffsetT))
}
/// Push a Push'able value onto the front of the in-progress data.
///
/// This function uses traits to provide a unified API for writing
/// scalars, tables, vectors, and WIPOffsets.
#[inline]
pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> {
self.try_push(x).expect("Flatbuffer allocation failure")
}
/// Fallible version of [`push_slot`](Self::push_slot).
#[inline]
pub fn try_push_slot<X: Push + PartialEq>(
&mut self,
slotoff: VOffsetT,
x: X,
default: X,
) -> Result<(), A::Error> {
self.assert_nested("push_slot");
if x != default || self.force_defaults {
self.try_push_slot_always(slotoff, x)?;
}
Ok(())
}
/// Push a Push'able value onto the front of the in-progress data, and
@@ -258,19 +381,29 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// the default, then this is a no-op.
#[inline]
pub fn push_slot<X: Push + PartialEq>(&mut self, slotoff: VOffsetT, x: X, default: X) {
self.assert_nested("push_slot");
if x != default || self.force_defaults {
self.push_slot_always(slotoff, x);
}
self.try_push_slot(slotoff, x, default)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`push_slot_always`](Self::push_slot_always).
#[inline]
pub fn try_push_slot_always<X: Push>(
&mut self,
slotoff: VOffsetT,
x: X,
) -> Result<(), A::Error> {
self.assert_nested("push_slot_always");
let off = self.try_push(x)?;
self.track_field(slotoff, off.value());
Ok(())
}
/// Push a Push'able value onto the front of the in-progress data, and
/// store a reference to it in the in-progress vtable.
#[inline]
pub fn push_slot_always<X: Push>(&mut self, slotoff: VOffsetT, x: X) {
self.assert_nested("push_slot_always");
let off = self.push(x);
self.track_field(slotoff, off.value());
self.try_push_slot_always(slotoff, x)
.expect("Flatbuffer allocation failure")
}
/// Retrieve the number of vtables that have been serialized into the
@@ -295,6 +428,22 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
WIPOffset::new(self.used_space() as UOffsetT)
}
/// Fallible version of [`end_table`](Self::end_table).
#[inline]
pub fn try_end_table(
&mut self,
off: WIPOffset<TableUnfinishedWIPOffset>,
) -> Result<WIPOffset<TableFinishedWIPOffset>, A::Error> {
self.assert_nested("end_table");
let o = self.write_vtable(off)?;
self.nested = false;
self.field_locs.clear();
Ok(WIPOffset::new(o.value()))
}
/// End a Table write.
///
/// Asserts that the builder is in a nested state.
@@ -303,14 +452,19 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
&mut self,
off: WIPOffset<TableUnfinishedWIPOffset>,
) -> WIPOffset<TableFinishedWIPOffset> {
self.assert_nested("end_table");
self.try_end_table(off)
.expect("Flatbuffer allocation failure")
}
let o = self.write_vtable(off);
self.nested = false;
self.field_locs.clear();
WIPOffset::new(o.value())
/// Fallible version of [`start_vector`](Self::start_vector).
#[inline]
pub fn try_start_vector<T: Push>(&mut self, num_items: usize) -> Result<(), A::Error> {
self.assert_not_nested(
"start_vector can not be called when a table or vector is under construction",
);
self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET))?;
self.nested = true;
Ok(())
}
/// Start a Vector write.
@@ -322,11 +476,20 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// function will want to use `push` to add values.
#[inline]
pub fn start_vector<T: Push>(&mut self, num_items: usize) {
self.assert_not_nested(
"start_vector can not be called when a table or vector is under construction",
);
self.nested = true;
self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET));
self.try_start_vector::<T>(num_items)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`end_vector`](Self::end_vector).
#[inline]
pub fn try_end_vector<T: Push>(
&mut self,
num_elems: usize,
) -> Result<WIPOffset<Vector<'fbb, T>>, A::Error> {
self.assert_nested("end_vector");
let o = self.try_push::<UOffsetT>(num_elems as UOffsetT)?;
self.nested = false;
Ok(WIPOffset::new(o.value()))
}
/// End a Vector write.
@@ -337,14 +500,54 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// Asserts that the builder is in a nested state.
#[inline]
pub fn end_vector<T: Push>(&mut self, num_elems: usize) -> WIPOffset<Vector<'fbb, T>> {
self.assert_nested("end_vector");
self.nested = false;
let o = self.push::<UOffsetT>(num_elems as UOffsetT);
WIPOffset::new(o.value())
self.try_end_vector::<T>(num_elems)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_shared_string`](Self::create_shared_string).
///
/// Uses a HashMap to track previously written strings, providing O(1)
/// amortized lookup and insertion.
#[cfg(feature = "std")]
#[inline]
pub fn try_create_shared_string<'a: 'b, 'b>(
&'a mut self,
s: &'b str,
) -> Result<WIPOffset<&'fbb str>, A::Error> {
self.assert_not_nested(
"create_shared_string can not be called when a table or vector is under construction",
);
if let Some(&offset) = self.strings_pool.get(s) {
return Ok(offset);
}
let address = WIPOffset::new(self.try_create_byte_string(s.as_bytes())?.value());
self.strings_pool.insert(s.to_owned(), address);
Ok(address)
}
/// Create a utf8 string, and de-duplicate if already created.
///
/// Uses a HashMap to track previously written strings, providing O(1)
/// amortized lookup and insertion.
#[cfg(feature = "std")]
#[inline]
pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
self.try_create_shared_string(s)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_shared_string`](Self::create_shared_string).
///
/// Uses a sorted Vec with binary search to track previously written
/// strings when in `no_std` mode.
#[cfg(not(feature = "std"))]
#[inline]
pub fn try_create_shared_string<'a: 'b, 'b>(
&'a mut self,
s: &'b str,
) -> Result<WIPOffset<&'fbb str>, A::Error> {
self.assert_not_nested(
"create_shared_string can not be called when a table or vector is under construction",
);
@@ -355,68 +558,95 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
let found = self.strings_pool.binary_search_by(|offset| {
let ptr = offset.value() as usize;
// Gets The pointer to the size of the string
let str_memory = &buf[buf.len() - ptr..];
// Gets the size of the written string from buffer
let size =
u32::from_le_bytes([str_memory[0], str_memory[1], str_memory[2], str_memory[3]])
as usize;
// Size of the string size
let string_size: usize = 4;
// Fetches actual string bytes from index of string after string size
// to the size of string plus string size
let iter = str_memory[string_size..size + string_size].iter();
// Compares bytes of fetched string and current writable string
iter.cloned().cmp(s.bytes())
let size = u32::from_le_bytes([
str_memory[0],
str_memory[1],
str_memory[2],
str_memory[3],
]) as usize;
let stored = &str_memory[4..4 + size];
stored.cmp(s.as_bytes())
});
match found {
Ok(index) => self.strings_pool[index],
Ok(index) => Ok(self.strings_pool[index]),
Err(index) => {
let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value());
let address =
WIPOffset::new(self.try_create_byte_string(s.as_bytes())?.value());
self.strings_pool.insert(index, address);
address
Ok(address)
}
}
}
/// Create a utf8 string, and de-duplicate if already created.
///
/// Uses a sorted Vec with binary search to track previously written
/// strings when in `no_std` mode.
#[cfg(not(feature = "std"))]
#[inline]
pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
self.try_create_shared_string(s)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_string`](Self::create_string).
#[inline]
pub fn try_create_string<'a: 'b, 'b>(
&'a mut self,
s: &'b str,
) -> Result<WIPOffset<&'fbb str>, A::Error> {
self.assert_not_nested(
"create_string can not be called when a table or vector is under construction",
);
Ok(WIPOffset::new(
self.try_create_byte_string(s.as_bytes())?.value(),
))
}
/// Create a utf8 string.
///
/// The wire format represents this as a zero-terminated byte vector.
#[inline]
pub fn create_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
self.try_create_string(s)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_byte_string`](Self::create_byte_string).
#[inline]
pub fn try_create_byte_string(
&mut self,
data: &[u8],
) -> Result<WIPOffset<&'fbb [u8]>, A::Error> {
self.assert_not_nested(
"create_string can not be called when a table or vector is under construction",
"create_byte_string can not be called when a table or vector is under construction",
);
WIPOffset::new(self.create_byte_string(s.as_bytes()).value())
self.align(data.len() + 1, PushAlignment::new(SIZE_UOFFSET))?;
self.try_push(0u8)?;
self.push_bytes_unprefixed(data)?;
self.try_push(data.len() as UOffsetT)?;
Ok(WIPOffset::new(self.used_space() as UOffsetT))
}
/// Create a zero-terminated byte vector.
#[inline]
pub fn create_byte_string(&mut self, data: &[u8]) -> WIPOffset<&'fbb [u8]> {
self.assert_not_nested(
"create_byte_string can not be called when a table or vector is under construction",
);
self.align(data.len() + 1, PushAlignment::new(SIZE_UOFFSET));
self.push(0u8);
self.push_bytes_unprefixed(data);
self.push(data.len() as UOffsetT);
WIPOffset::new(self.used_space() as UOffsetT)
self.try_create_byte_string(data)
.expect("Flatbuffer allocation failure")
}
/// 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`.
/// Fallible version of [`create_vector`](Self::create_vector).
#[inline]
pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
pub fn try_create_vector<'a: 'b, 'b, T: Push + 'b>(
&'a mut self,
items: &'b [T],
) -> WIPOffset<Vector<'fbb, T::Output>> {
) -> Result<WIPOffset<Vector<'fbb, T::Output>>, A::Error> {
let elem_size = T::size();
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.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.head.distance_to_end();
@@ -430,7 +660,38 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
unsafe { item.push(out, written_len) };
}
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
Ok(WIPOffset::new(
self.try_push::<UOffsetT>(items.len() as UOffsetT)?.value(),
))
}
/// 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 + 'b>(
&'a mut self,
items: &'b [T],
) -> WIPOffset<Vector<'fbb, T::Output>> {
self.try_create_vector(items)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_vector_from_iter`](Self::create_vector_from_iter).
#[inline]
pub fn try_create_vector_from_iter<T: Push>(
&mut self,
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
) -> Result<WIPOffset<Vector<'fbb, T::Output>>, A::Error> {
let elem_size = T::size();
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET))?;
let mut actual = 0;
for item in items.rev() {
self.try_push(item)?;
actual += 1;
}
Ok(WIPOffset::new(self.try_push::<UOffsetT>(actual)?.value()))
}
/// Create a vector of Push-able objects.
@@ -442,14 +703,8 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
&mut self,
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
) -> WIPOffset<Vector<'fbb, T::Output>> {
let elem_size = T::size();
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>(actual).value())
self.try_create_vector_from_iter(items)
.expect("Flatbuffer allocation failure")
}
/// Set whether default values are stored.
@@ -512,13 +767,34 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
assert!(o != 0, "missing required field {}", assert_msg_name);
}
/// Fallible version of [`finish_size_prefixed`](Self::finish_size_prefixed).
#[inline]
pub fn try_finish_size_prefixed<T>(
&mut self,
root: WIPOffset<T>,
file_identifier: Option<&str>,
) -> Result<(), A::Error> {
self.finish_with_opts(root, file_identifier, true)
}
/// Finalize the FlatBuffer by: aligning it, pushing an optional file
/// identifier on to it, pushing a size prefix on to it, and marking the
/// internal state of the FlatBufferBuilder as `finished`. Afterwards,
/// users can call `finished_data` to get the resulting data.
#[inline]
pub fn finish_size_prefixed<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
self.finish_with_opts(root, file_identifier, true);
self.try_finish_size_prefixed(root, file_identifier)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`finish`](Self::finish).
#[inline]
pub fn try_finish<T>(
&mut self,
root: WIPOffset<T>,
file_identifier: Option<&str>,
) -> Result<(), A::Error> {
self.finish_with_opts(root, file_identifier, false)
}
/// Finalize the FlatBuffer by: aligning it, pushing an optional file
@@ -527,7 +803,14 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// `finished_data` to get the resulting data.
#[inline]
pub fn finish<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
self.finish_with_opts(root, file_identifier, false);
self.try_finish(root, file_identifier)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`finish_minimal`](Self::finish_minimal).
#[inline]
pub fn try_finish_minimal<T>(&mut self, root: WIPOffset<T>) -> Result<(), A::Error> {
self.finish_with_opts(root, None, false)
}
/// Finalize the FlatBuffer by: aligning it and marking the internal state
@@ -535,7 +818,8 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// `finished_data` to get the resulting data.
#[inline]
pub fn finish_minimal<T>(&mut self, root: WIPOffset<T>) {
self.finish_with_opts(root, None, false);
self.try_finish_minimal(root)
.expect("Flatbuffer allocation failure")
}
#[inline]
@@ -553,13 +837,13 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
fn write_vtable(
&mut self,
table_tail_revloc: WIPOffset<TableUnfinishedWIPOffset>,
) -> WIPOffset<VTableWIPOffset> {
) -> Result<WIPOffset<VTableWIPOffset>, A::Error> {
self.assert_nested("write_vtable");
// Write the vtable offset, which is the start of any Table.
// We fill its value later.
let object_revloc_to_vtable: WIPOffset<VTableWIPOffset> =
WIPOffset::new(self.push::<UOffsetT>(0xF0F0_F0F0).value());
WIPOffset::new(self.try_push::<UOffsetT>(0xF0F0_F0F0)?.value());
// Layout of the data this function will create when a new vtable is
// needed.
@@ -602,7 +886,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
// fill the WIP vtable with zeros:
let vtable_byte_len = get_vtable_byte_len(&self.field_locs);
self.make_space(vtable_byte_len);
self.make_space(vtable_byte_len)?;
// compute the length of the table (not vtable!) in bytes:
let table_object_size = object_revloc_to_vtable.value() - table_tail_revloc.value();
@@ -627,13 +911,15 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
}
}
let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)];
let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| {
let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize;
// Safety:
// Already written vtables are valid by construction
let old_vtable = unsafe { VTable::init(&self.allocator, 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.allocator.len() - *old_vtable_revpos as usize;
// Safety:
// Already written vtables are valid by construction
let old_vtable = unsafe { VTable::init(&self.allocator, 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.
@@ -671,17 +957,18 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.field_locs.clear();
object_revloc_to_vtable
Ok(object_revloc_to_vtable)
}
// Only call this when you know it is safe to double the size of the buffer.
#[inline]
fn grow_allocator(&mut self) {
fn grow_allocator(&mut self) -> Result<(), A::Error> {
let starting_active_size = self.used_space();
self.allocator.grow_downwards().expect("Flatbuffer allocation failure");
self.allocator.grow_downwards()?;
let ending_active_size = self.used_space();
debug_assert_eq!(starting_active_size, ending_active_size);
Ok(())
}
// with or without a size prefix changes how we load the data, so finish*
@@ -691,7 +978,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
root: WIPOffset<T>,
file_identifier: Option<&str>,
size_prefixed: bool,
) {
) -> Result<(), A::Error> {
self.assert_not_finished("buffer cannot be finished when it is already finished");
self.assert_not_nested(
"buffer cannot be finished when a table or vector is under construction",
@@ -704,34 +991,40 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
// for the size prefix:
let b = if size_prefixed { SIZE_UOFFSET } else { 0 };
// for the file identifier (a string that is not zero-terminated):
let c = if file_identifier.is_some() { FILE_IDENTIFIER_LENGTH } else { 0 };
let c = if file_identifier.is_some() {
FILE_IDENTIFIER_LENGTH
} else {
0
};
a + b + c
};
{
let ma = PushAlignment::new(self.min_align);
self.align(to_align, ma);
self.align(to_align, ma)?;
}
if let Some(ident) = file_identifier {
debug_assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
self.push_bytes_unprefixed(ident.as_bytes());
self.push_bytes_unprefixed(ident.as_bytes())?;
}
self.push(root);
self.try_push(root)?;
if size_prefixed {
let sz = self.used_space() as UOffsetT;
self.push::<UOffsetT>(sz);
self.try_push::<UOffsetT>(sz)?;
}
self.finished = true;
Ok(())
}
#[inline]
fn align(&mut self, len: usize, alignment: PushAlignment) {
fn align(&mut self, len: usize, alignment: PushAlignment) -> Result<(), A::Error> {
self.track_min_align(alignment.value());
let s = self.used_space() as usize;
self.make_space(padding_bytes(s + len, alignment.value()));
self.make_space(padding_bytes(s + len, alignment.value()))?;
Ok(())
}
#[inline]
@@ -740,31 +1033,34 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
}
#[inline]
fn push_bytes_unprefixed(&mut self, x: &[u8]) -> UOffsetT {
let n = self.make_space(x.len());
fn push_bytes_unprefixed(&mut self, x: &[u8]) -> Result<UOffsetT, A::Error> {
let n = self.make_space(x.len())?;
self.allocator[n.range_to(n + x.len())].copy_from_slice(x);
n.to_forward_index(&self.allocator) as UOffsetT
Ok(n.to_forward_index(&self.allocator) as UOffsetT)
}
#[inline]
fn make_space(&mut self, want: usize) -> ReverseIndex {
self.ensure_capacity(want);
fn make_space(&mut self, want: usize) -> Result<ReverseIndex, A::Error> {
self.ensure_capacity(want)?;
self.head -= want;
self.head
Ok(self.head)
}
#[inline]
fn ensure_capacity(&mut self, want: usize) -> usize {
fn ensure_capacity(&mut self, want: usize) -> Result<usize, A::Error> {
if self.unused_ready_space() >= want {
return want;
return Ok(want);
}
assert!(want <= FLATBUFFERS_MAX_BUFFER_SIZE, "cannot grow buffer beyond 2 gigabytes");
assert!(
want <= FLATBUFFERS_MAX_BUFFER_SIZE,
"cannot grow buffer beyond 2 gigabytes"
);
while self.unused_ready_space() < want {
self.grow_allocator();
self.grow_allocator()?;
}
want
Ok(want)
}
#[inline]
fn unused_ready_space(&self) -> usize {
@@ -931,6 +1227,33 @@ impl<T> IndexMut<ReverseIndexRange> for [T] {
#[cfg(test)]
mod tests {
use super::*;
use core::sync::atomic::{AtomicUsize, Ordering};
use std::alloc::{GlobalAlloc, Layout, System};
static ALLOC_COUNT: AtomicUsize = AtomicUsize::new(0);
struct CountingAllocator;
unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOC_COUNT.fetch_add(1, Ordering::Relaxed);
unsafe { System.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
}
#[global_allocator]
static GLOBAL: CountingAllocator = CountingAllocator;
fn reset_alloc_count() {
ALLOC_COUNT.store(0, Ordering::Relaxed);
}
fn alloc_count() -> usize {
ALLOC_COUNT.load(Ordering::Relaxed)
}
#[test]
fn reverse_index_test() {
@@ -940,4 +1263,150 @@ mod tests {
assert_eq!(&buf[idx.range_to(idx + 1)], &[4]);
assert_eq!(idx.to_forward_index(&buf), 4);
}
#[test]
fn with_internal_capacity_preallocates_vecs() {
let mut builder = FlatBufferBuilder::with_internal_capacity(64, 8, 16, 32);
assert!(builder.allocator.len() >= 64);
assert!(builder.field_locs.capacity() >= 8);
assert!(builder.written_vtable_revpos.capacity() >= 16);
assert!(builder.strings_pool.capacity() >= 32);
assert!(builder.field_locs.is_empty());
assert!(builder.written_vtable_revpos.is_empty());
assert!(builder.strings_pool.is_empty());
// Reset the allocation counter after builder construction
reset_alloc_count();
// Add a shared string and verify it lands in the pool
let s1 = builder.create_shared_string("hello");
assert_eq!(builder.strings_pool.len(), 1);
// Adding the same string again should reuse the pooled entry
let s2 = builder.create_shared_string("hello");
assert_eq!(builder.strings_pool.len(), 1);
assert_eq!(s1.value(), s2.value());
// A different string should add a new entry
let _s3 = builder.create_shared_string("world");
assert_eq!(builder.strings_pool.len(), 2);
// With sufficient preallocated capacity, no additional allocations
// should have occurred for the internal vecs during the operations above
let allocs = alloc_count();
assert_eq!(
allocs, 0,
"expected 0 allocations after builder construction, got {}",
allocs
);
}
/// A test allocator that fails after a specified number of grow operations.
struct FailingAllocator {
inner: DefaultAllocator,
grows_remaining: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct AllocationError;
impl core::fmt::Display for AllocationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "allocation failed")
}
}
impl FailingAllocator {
fn new(initial_size: usize, max_grows: usize) -> Self {
Self {
inner: DefaultAllocator::from_vec(vec![0u8; initial_size]),
grows_remaining: max_grows,
}
}
}
impl Deref for FailingAllocator {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for FailingAllocator {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
unsafe impl Allocator for FailingAllocator {
type Error = AllocationError;
fn grow_downwards(&mut self) -> Result<(), Self::Error> {
if self.grows_remaining == 0 {
return Err(AllocationError);
}
self.grows_remaining -= 1;
// DefaultAllocator returns Infallible, so unwrap is safe
self.inner.grow_downwards().unwrap();
Ok(())
}
fn len(&self) -> usize {
self.inner.len()
}
}
#[test]
fn try_push_propagates_allocation_error() {
let allocator = FailingAllocator::new(1, 0);
let mut builder = FlatBufferBuilder::new_in(allocator);
let result = builder.try_push::<u64>(0x1234567890ABCDEF);
assert!(result.is_err());
}
#[test]
fn try_create_string_propagates_allocation_error() {
let allocator = FailingAllocator::new(1, 0);
let mut builder = FlatBufferBuilder::new_in(allocator);
let result = builder.try_create_string("hello world");
assert!(result.is_err());
}
#[test]
fn try_create_vector_propagates_allocation_error() {
let allocator = FailingAllocator::new(1, 0);
let mut builder = FlatBufferBuilder::new_in(allocator);
let result = builder.try_create_vector(&[1u32, 2, 3, 4, 5]);
assert!(result.is_err());
}
#[test]
fn try_methods_succeed_with_sufficient_capacity() {
let allocator = FailingAllocator::new(1, 10);
let mut builder = FlatBufferBuilder::new_in(allocator);
let result = builder.try_create_string("hello");
assert!(result.is_ok());
let result = builder.try_create_vector(&[1u32, 2, 3]);
assert!(result.is_ok());
}
#[test]
fn try_finish_propagates_allocation_error() {
let allocator = FailingAllocator::new(1, 3);
let mut builder = FlatBufferBuilder::new_in(allocator);
let start = builder.start_table();
let table = builder
.try_end_table(start)
.expect("end_table should succeed with 3 grows");
let result = builder.try_finish_minimal(table);
assert!(result.is_err(), "finish should fail after grows exhausted");
}
}
+25
View File
@@ -83,6 +83,11 @@ macro_rules! impl_push_for_endian_scalar {
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
emplace_scalar::<$ty>(dst, *self);
}
#[inline]
fn alignment() -> PushAlignment {
PushAlignment::new(size_of::<$ty>())
}
}
};
}
@@ -98,3 +103,23 @@ impl_push_for_endian_scalar!(u64);
impl_push_for_endian_scalar!(i64);
impl_push_for_endian_scalar!(f32);
impl_push_for_endian_scalar!(f64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn endian_scalar_push_alignment_matches_wire_size() {
assert_eq!(<bool as Push>::alignment().value(), 1);
assert_eq!(<u8 as Push>::alignment().value(), 1);
assert_eq!(<i8 as Push>::alignment().value(), 1);
assert_eq!(<u16 as Push>::alignment().value(), 2);
assert_eq!(<i16 as Push>::alignment().value(), 2);
assert_eq!(<u32 as Push>::alignment().value(), 4);
assert_eq!(<i32 as Push>::alignment().value(), 4);
assert_eq!(<f32 as Push>::alignment().value(), 4);
assert_eq!(<u64 as Push>::alignment().value(), 8);
assert_eq!(<i64 as Push>::alignment().value(), 8);
assert_eq!(<f64 as Push>::alignment().value(), 8);
}
}
+15 -1
View File
@@ -107,6 +107,20 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
key: K,
f: fn(&<T as Follow<'a>>::Inner, &K) -> Ordering,
) -> Option<T::Inner> {
self.lookup_index_by_key(key, f).map(|idx| self.get(idx))
}
/// Binary search by key, returning the index of the matching element.
///
/// This is similar to `lookup_by_key`, but returns the index of the found
/// element rather than the element itself. This is useful when you need
/// to reference elements by their position in the vector.
#[inline(always)]
pub fn lookup_index_by_key<K: Ord>(
&self,
key: K,
f: fn(&<T as Follow<'a>>::Inner, &K) -> Ordering,
) -> Option<usize> {
if self.is_empty() {
return None;
}
@@ -118,7 +132,7 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
let mid = (left + right) / 2;
let value = self.get(mid);
match f(&value, &key) {
Ordering::Equal => return Some(value),
Ordering::Equal => return Some(mid),
Ordering::Less => left = mid + 1,
Ordering::Greater => {
if mid == 0 {
+1 -1
View File
@@ -492,8 +492,8 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
Ok(self)
}
_ => InvalidFlatbuffer::new_inconsistent_union(
key_field_name.into(),
val_field_name.into(),
key_field_name.into(),
),
}
}
+1 -1
View File
@@ -397,8 +397,8 @@ fn verify_union<'a, 'b, 'c>(
}
} else {
return InvalidFlatbuffer::new_inconsistent_union(
format!("{}_type", field.name()),
field.name().to_string(),
format!("{}_type", field.name()),
)?;
}
+1 -1
View File
@@ -643,7 +643,7 @@ inline ::flatbuffers::Offset<Monster> Monster::Pack(::flatbuffers::FlatBufferBui
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0;
auto _color = _o->color;
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<::flatbuffers::Offset<MyGame::Sample::Weapon>> (_o->weapons.size(), [](size_t i, _VectorArgs *__va) { return CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0;
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<::flatbuffers::Offset<MyGame::Sample::Weapon>> (_o->weapons.size(), [](size_t i, _VectorArgs *__va) { return MyGame::Sample::CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0;
auto _equipped_type = _o->equipped.type;
auto _equipped = _o->equipped.Pack(_fbb);
auto _path = _o->path.size() ? _fbb.CreateVectorOfStructs(_o->path) : 0;
+65 -69
View File
@@ -113,12 +113,12 @@ public struct MyGame_Sample_Vec3: NativeStruct, FlatbuffersVectorInitializable,
}
extension MyGame_Sample_Vec3: Encodable {
enum CodingKeys: String, CodingKey {
case x = "x"
case y = "y"
case z = "z"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if x != 0.0 {
@@ -161,7 +161,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferStruct, FlatbuffersVectorIni
}
}
public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -170,51 +170,49 @@ public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializ
private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private enum VTOFFSET: VOffset {
case pos = 4
case mana = 6
case hp = 8
case name = 10
case inventory = 14
case color = 16
case weapons = 18
case equippedType = 20
case equipped = 22
case path = 24
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
private struct VT {
static let pos: VOffset = 4
static let mana: VOffset = 6
static let hp: VOffset = 8
static let name: VOffset = 10
static let inventory: VOffset = 14
static let color: VOffset = 16
static let weapons: VOffset = 18
static let equippedType: VOffset = 20
static let equipped: VOffset = 22
static let path: VOffset = 24
}
public var pos: MyGame_Sample_Vec3? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : _accessor.readBuffer(of: MyGame_Sample_Vec3.self, at: o) }
public var mutablePos: MyGame_Sample_Vec3_Mutable? { let o = _accessor.offset(VTOFFSET.pos.v); return o == 0 ? nil : MyGame_Sample_Vec3_Mutable(_accessor.bb, o: o + _accessor.position) }
public var mana: Int16 { let o = _accessor.offset(VTOFFSET.mana.v); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(mana: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.mana.v); return _accessor.mutate(mana, index: o) }
public var hp: Int16 { let o = _accessor.offset(VTOFFSET.hp.v); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(hp: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.hp.v); return _accessor.mutate(hp, index: o) }
public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) }
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
public var inventory: FlatbufferVector<UInt8> { return _accessor.vector(at: VTOFFSET.inventory.v, byteSize: 1) }
public func mutate(inventory: UInt8, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.inventory.v); return _accessor.directMutate(inventory, index: _accessor.vector(at: o) + index * 1) }
public func withUnsafePointerToInventory<T>(_ body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return try _accessor.withUnsafePointerToSlice(at: VTOFFSET.inventory.v, body: body) }
public var color: MyGame_Sample_Color { let o = _accessor.offset(VTOFFSET.color.v); return o == 0 ? .blue : MyGame_Sample_Color(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .blue }
@discardableResult public func mutate(color: MyGame_Sample_Color) -> Bool {let o = _accessor.offset(VTOFFSET.color.v); return _accessor.mutate(color.rawValue, index: o) }
public var weapons: FlatbufferVector<MyGame_Sample_Weapon> { return _accessor.vector(at: VTOFFSET.weapons.v, byteSize: 4) }
public var equippedType: MyGame_Sample_Equipment { let o = _accessor.offset(VTOFFSET.equippedType.v); return o == 0 ? .none_ : MyGame_Sample_Equipment(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none_ }
public func equipped<T: FlatbuffersInitializable>(type: T.Type) -> T? { let o = _accessor.offset(VTOFFSET.equipped.v); return o == 0 ? nil : _accessor.union(o) }
public var path: FlatbufferVector<MyGame_Sample_Vec3> { return _accessor.vector(at: VTOFFSET.path.v, byteSize: 12) }
public var mutablePath: FlatbufferVector<MyGame_Sample_Vec3_Mutable> { return _accessor.vector(at: VTOFFSET.path.v, byteSize: 12) }
public func withUnsafePointerToPath<T>(_ body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return try _accessor.withUnsafePointerToSlice(at: VTOFFSET.path.v, body: body) }
public var pos: MyGame_Sample_Vec3? { let o = _accessor.offset(VT.pos); return o == 0 ? nil : _accessor.readBuffer(of: MyGame_Sample_Vec3.self, at: o) }
public var mutablePos: MyGame_Sample_Vec3_Mutable? { let o = _accessor.offset(VT.pos); return o == 0 ? nil : MyGame_Sample_Vec3_Mutable(_accessor.bb, o: o + _accessor.position) }
public var mana: Int16 { let o = _accessor.offset(VT.mana); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(mana: Int16) -> Bool {let o = _accessor.offset(VT.mana); return _accessor.mutate(mana, index: o) }
public var hp: Int16 { let o = _accessor.offset(VT.hp); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(hp: Int16) -> Bool {let o = _accessor.offset(VT.hp); return _accessor.mutate(hp, index: o) }
public var name: String? { let o = _accessor.offset(VT.name); return o == 0 ? nil : _accessor.string(at: o) }
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VT.name) }
public var inventory: FlatbufferVector<UInt8> { return _accessor.vector(at: VT.inventory, byteSize: 1) }
public func mutate(inventory: UInt8, at index: Int32) -> Bool { let o = _accessor.offset(VT.inventory); return _accessor.directMutate(inventory, index: _accessor.vector(at: o) + index * 1) }
public func withUnsafePointerToInventory<T>(_ body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return try _accessor.withUnsafePointerToSlice(at: VT.inventory, body: body) }
public var color: MyGame_Sample_Color { let o = _accessor.offset(VT.color); return o == 0 ? .blue : MyGame_Sample_Color(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .blue }
@discardableResult public func mutate(color: MyGame_Sample_Color) -> Bool {let o = _accessor.offset(VT.color); return _accessor.mutate(color.rawValue, index: o) }
public var weapons: FlatbufferVector<MyGame_Sample_Weapon> { return _accessor.vector(at: VT.weapons, byteSize: 4) }
public var equippedType: MyGame_Sample_Equipment { let o = _accessor.offset(VT.equippedType); return o == 0 ? .none_ : MyGame_Sample_Equipment(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none_ }
public func equipped<T: FlatbuffersInitializable>(type: T.Type) -> T? { let o = _accessor.offset(VT.equipped); return o == 0 ? nil : _accessor.union(o) }
public var path: FlatbufferVector<MyGame_Sample_Vec3> { return _accessor.vector(at: VT.path, byteSize: 12) }
public var mutablePath: FlatbufferVector<MyGame_Sample_Vec3_Mutable> { return _accessor.vector(at: VT.path, byteSize: 12) }
public func withUnsafePointerToPath<T>(_ body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return try _accessor.withUnsafePointerToSlice(at: VT.path, body: body) }
public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 11) }
public static func add(pos: MyGame_Sample_Vec3?, _ fbb: inout FlatBufferBuilder) { guard let pos = pos else { return }; fbb.create(struct: pos, position: VTOFFSET.pos.p) }
public static func add(mana: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: mana, def: 150, at: VTOFFSET.mana.p) }
public static func add(hp: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: hp, def: 100, at: VTOFFSET.hp.p) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
public static func addVectorOf(inventory: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: inventory, at: VTOFFSET.inventory.p) }
public static func add(color: MyGame_Sample_Color, _ fbb: inout FlatBufferBuilder) { fbb.add(element: color.rawValue, def: 2, at: VTOFFSET.color.p) }
public static func addVectorOf(weapons: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: weapons, at: VTOFFSET.weapons.p) }
public static func add(equippedType: MyGame_Sample_Equipment, _ fbb: inout FlatBufferBuilder) { fbb.add(element: equippedType.rawValue, def: 0, at: VTOFFSET.equippedType.p) }
public static func add(equipped: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: equipped, at: VTOFFSET.equipped.p) }
public static func addVectorOf(path: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: path, at: VTOFFSET.path.p) }
public static func add(pos: MyGame_Sample_Vec3?, _ fbb: inout FlatBufferBuilder) { guard let pos = pos else { return }; fbb.create(struct: pos, position: VT.pos) }
public static func add(mana: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: mana, def: 150, at: VT.mana) }
public static func add(hp: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: hp, def: 100, at: VT.hp) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VT.name) }
public static func addVectorOf(inventory: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: inventory, at: VT.inventory) }
public static func add(color: MyGame_Sample_Color, _ fbb: inout FlatBufferBuilder) { fbb.add(element: color.rawValue, def: 2, at: VT.color) }
public static func addVectorOf(weapons: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: weapons, at: VT.weapons) }
public static func add(equippedType: MyGame_Sample_Equipment, _ fbb: inout FlatBufferBuilder) { fbb.add(element: equippedType.rawValue, def: 0, at: VT.equippedType) }
public static func add(equipped: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: equipped, at: VT.equipped) }
public static func addVectorOf(path: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: path, at: VT.path) }
public static func startVectorOfPath(_ size: Int, in builder: inout FlatBufferBuilder) {
builder.startVector(size * MemoryLayout<MyGame_Sample_Vec3>.size, elementSize: MemoryLayout<MyGame_Sample_Vec3>.alignment)
}
@@ -293,14 +291,14 @@ public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializ
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
var _v = try verifier.visitTable(at: position)
try _v.visit(field: VTOFFSET.pos.p, fieldName: "pos", required: false, type: MyGame_Sample_Vec3.self)
try _v.visit(field: VTOFFSET.mana.p, fieldName: "mana", required: false, type: Int16.self)
try _v.visit(field: VTOFFSET.hp.p, fieldName: "hp", required: false, type: Int16.self)
try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
try _v.visit(field: VTOFFSET.inventory.p, fieldName: "inventory", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
try _v.visit(field: VTOFFSET.color.p, fieldName: "color", required: false, type: MyGame_Sample_Color.self)
try _v.visit(field: VTOFFSET.weapons.p, fieldName: "weapons", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Sample_Weapon>, MyGame_Sample_Weapon>>.self)
try _v.visit(unionKey: VTOFFSET.equippedType.p, unionField: VTOFFSET.equipped.p, unionKeyName: "equippedType", fieldName: "equipped", required: false, completion: { (verifier, key: MyGame_Sample_Equipment, pos) in
try _v.visit(field: VT.pos, fieldName: "pos", required: false, type: MyGame_Sample_Vec3.self)
try _v.visit(field: VT.mana, fieldName: "mana", required: false, type: Int16.self)
try _v.visit(field: VT.hp, fieldName: "hp", required: false, type: Int16.self)
try _v.visit(field: VT.name, fieldName: "name", required: false, type: ForwardOffset<String>.self)
try _v.visit(field: VT.inventory, fieldName: "inventory", required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
try _v.visit(field: VT.color, fieldName: "color", required: false, type: MyGame_Sample_Color.self)
try _v.visit(field: VT.weapons, fieldName: "weapons", required: false, type: ForwardOffset<Vector<ForwardOffset<MyGame_Sample_Weapon>, MyGame_Sample_Weapon>>.self)
try _v.visit(unionKey: VT.equippedType, unionField: VT.equipped, unionKeyName: "equippedType", fieldName: "equipped", required: false, completion: { (verifier, key: MyGame_Sample_Equipment, pos) in
switch key {
case .none_:
break // NOTE - SWIFT doesnt support none
@@ -308,13 +306,12 @@ public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializ
try ForwardOffset<MyGame_Sample_Weapon>.verify(&verifier, at: pos, of: MyGame_Sample_Weapon.self)
}
})
try _v.visit(field: VTOFFSET.path.p, fieldName: "path", required: false, type: ForwardOffset<Vector<MyGame_Sample_Vec3, MyGame_Sample_Vec3>>.self)
try _v.visit(field: VT.path, fieldName: "path", required: false, type: ForwardOffset<Vector<MyGame_Sample_Vec3, MyGame_Sample_Vec3>>.self)
_v.finish()
}
}
extension MyGame_Sample_Monster: Encodable {
enum CodingKeys: String, CodingKey {
case pos = "pos"
case mana = "mana"
@@ -327,6 +324,7 @@ extension MyGame_Sample_Monster: Encodable {
case equipped = "equipped"
case path = "path"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(pos, forKey: .pos)
@@ -402,7 +400,7 @@ public class MyGame_Sample_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Sample_Monster.self) }
}
public struct MyGame_Sample_Weapon: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
public struct MyGame_Sample_Weapon: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -411,20 +409,18 @@ public struct MyGame_Sample_Weapon: FlatBufferTable, FlatbuffersVectorInitializa
private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private enum VTOFFSET: VOffset {
case name = 4
case damage = 6
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
private struct VT {
static let name: VOffset = 4
static let damage: VOffset = 6
}
public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) }
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
public var damage: Int16 { let o = _accessor.offset(VTOFFSET.damage.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(damage: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.damage.v); return _accessor.mutate(damage, index: o) }
public var name: String? { let o = _accessor.offset(VT.name); return o == 0 ? nil : _accessor.string(at: o) }
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VT.name) }
public var damage: Int16 { let o = _accessor.offset(VT.damage); return o == 0 ? 0 : _accessor.readBuffer(of: Int16.self, at: o) }
@discardableResult public func mutate(damage: Int16) -> Bool {let o = _accessor.offset(VT.damage); return _accessor.mutate(damage, index: o) }
public static func startWeapon(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 2) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
public static func add(damage: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damage, def: 0, at: VTOFFSET.damage.p) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VT.name) }
public static func add(damage: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damage, def: 0, at: VT.damage) }
public static func endWeapon(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createWeapon(
_ fbb: inout FlatBufferBuilder,
@@ -461,18 +457,18 @@ public struct MyGame_Sample_Weapon: FlatBufferTable, FlatbuffersVectorInitializa
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
var _v = try verifier.visitTable(at: position)
try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
try _v.visit(field: VTOFFSET.damage.p, fieldName: "damage", required: false, type: Int16.self)
try _v.visit(field: VT.name, fieldName: "name", required: false, type: ForwardOffset<String>.self)
try _v.visit(field: VT.damage, fieldName: "damage", required: false, type: Int16.self)
_v.finish()
}
}
extension MyGame_Sample_Weapon: Encodable {
enum CodingKeys: String, CodingKey {
case name = "name"
case damage = "damage"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(name, forKey: .name)
+13 -13
View File
@@ -1,18 +1,18 @@
// Automatically generated by the Flatbuffers compiler. Do not modify.
// @generated
pub mod my_game {
use super::*;
pub mod sample {
use super::*;
mod color_generated;
pub use self::color_generated::*;
mod equipment_generated;
pub use self::equipment_generated::*;
mod vec_3_generated;
pub use self::vec_3_generated::*;
mod monster_generated;
pub use self::monster_generated::*;
mod weapon_generated;
pub use self::weapon_generated::*;
} // sample
pub mod sample {
use super::*;
mod color_generated;
pub use self::color_generated::*;
mod equipment_generated;
pub use self::equipment_generated::*;
mod vec_3_generated;
pub use self::vec_3_generated::*;
mod monster_generated;
pub use self::monster_generated::*;
mod weapon_generated;
pub use self::weapon_generated::*;
} // sample
} // my_game
@@ -2,64 +2,73 @@
// @generated
extern crate alloc;
use super::*;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_COLOR: i8 = 0;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MAX_COLOR: i8 = 2;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
#[allow(non_camel_case_types)]
pub const ENUM_VALUES_COLOR: [Color; 3] = [
Color::Red,
Color::Green,
Color::Blue,
Color::Red,
Color::Green,
Color::Blue,
];
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
pub struct Color(pub i8);
#[allow(non_upper_case_globals)]
impl Color {
pub const Red: Self = Self(0);
pub const Green: Self = Self(1);
pub const Blue: Self = Self(2);
pub const Red: Self = Self(0);
pub const Green: Self = Self(1);
pub const Blue: Self = Self(2);
pub const ENUM_MIN: i8 = 0;
pub const ENUM_MAX: i8 = 2;
pub const ENUM_VALUES: &'static [Self] = &[
Self::Red,
Self::Green,
Self::Blue,
];
/// Returns the variant's name or "" if unknown.
pub fn variant_name(self) -> Option<&'static str> {
match self {
Self::Red => Some("Red"),
Self::Green => Some("Green"),
Self::Blue => Some("Blue"),
_ => None,
pub const ENUM_MIN: i8 = 0;
pub const ENUM_MAX: i8 = 2;
pub const ENUM_VALUES: &'static [Self] = &[
Self::Red,
Self::Green,
Self::Blue,
];
/// Returns the variant's name or "" if unknown.
pub fn variant_name(self) -> Option<&'static str> {
match self {
Self::Red => Some("Red"),
Self::Green => Some("Green"),
Self::Blue => Some("Blue"),
_ => None,
}
}
}
}
impl ::core::fmt::Debug for Color {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() {
f.write_str(name)
} else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() {
f.write_str(name)
} else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
}
}
}
}
impl<'a> ::flatbuffers::Follow<'a> for Color {
type Inner = Self;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let b = unsafe { ::flatbuffers::read_scalar_at::<i8>(buf, loc) };
Self(b)
}
type Inner = Self;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let b = unsafe { ::flatbuffers::read_scalar_at::<i8>(buf, loc) };
Self(b)
}
}
impl ::flatbuffers::Push for Color {
type Output = Color;
#[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
unsafe { ::flatbuffers::emplace_scalar::<i8>(dst, self.0) };
@@ -67,26 +76,28 @@ impl ::flatbuffers::Push for Color {
}
impl ::flatbuffers::EndianScalar for Color {
type Scalar = i8;
#[inline]
fn to_little_endian(self) -> i8 {
self.0.to_le()
}
#[inline]
#[allow(clippy::wrong_self_convention)]
fn from_little_endian(v: i8) -> Self {
let b = i8::from_le(v);
Self(b)
}
type Scalar = i8;
#[inline]
fn to_little_endian(self) -> i8 {
self.0.to_le()
}
#[inline]
#[allow(clippy::wrong_self_convention)]
fn from_little_endian(v: i8) -> Self {
let b = i8::from_le(v);
Self(b)
}
}
impl<'a> ::flatbuffers::Verifiable for Color {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
i8::run_verifier(v, pos)
}
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
i8::run_verifier(v, pos)
}
}
impl ::flatbuffers::SimpleToVerifyInSlice for Color {}
@@ -2,60 +2,69 @@
// @generated
extern crate alloc;
use super::*;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_EQUIPMENT: u8 = 0;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MAX_EQUIPMENT: u8 = 1;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
#[allow(non_camel_case_types)]
pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [
Equipment::NONE,
Equipment::Weapon,
Equipment::NONE,
Equipment::Weapon,
];
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
pub struct Equipment(pub u8);
#[allow(non_upper_case_globals)]
impl Equipment {
pub const NONE: Self = Self(0);
pub const Weapon: Self = Self(1);
pub const NONE: Self = Self(0);
pub const Weapon: Self = Self(1);
pub const ENUM_MIN: u8 = 0;
pub const ENUM_MAX: u8 = 1;
pub const ENUM_VALUES: &'static [Self] = &[
Self::NONE,
Self::Weapon,
];
/// Returns the variant's name or "" if unknown.
pub fn variant_name(self) -> Option<&'static str> {
match self {
Self::NONE => Some("NONE"),
Self::Weapon => Some("Weapon"),
_ => None,
pub const ENUM_MIN: u8 = 0;
pub const ENUM_MAX: u8 = 1;
pub const ENUM_VALUES: &'static [Self] = &[
Self::NONE,
Self::Weapon,
];
/// Returns the variant's name or "" if unknown.
pub fn variant_name(self) -> Option<&'static str> {
match self {
Self::NONE => Some("NONE"),
Self::Weapon => Some("Weapon"),
_ => None,
}
}
}
}
impl ::core::fmt::Debug for Equipment {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() {
f.write_str(name)
} else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() {
f.write_str(name)
} else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
}
}
}
}
impl<'a> ::flatbuffers::Follow<'a> for Equipment {
type Inner = Self;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let b = unsafe { ::flatbuffers::read_scalar_at::<u8>(buf, loc) };
Self(b)
}
type Inner = Self;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let b = unsafe { ::flatbuffers::read_scalar_at::<u8>(buf, loc) };
Self(b)
}
}
impl ::flatbuffers::Push for Equipment {
type Output = Equipment;
#[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
unsafe { ::flatbuffers::emplace_scalar::<u8>(dst, self.0) };
@@ -63,75 +72,85 @@ impl ::flatbuffers::Push for Equipment {
}
impl ::flatbuffers::EndianScalar for Equipment {
type Scalar = u8;
#[inline]
fn to_little_endian(self) -> u8 {
self.0.to_le()
}
#[inline]
#[allow(clippy::wrong_self_convention)]
fn from_little_endian(v: u8) -> Self {
let b = u8::from_le(v);
Self(b)
}
type Scalar = u8;
#[inline]
fn to_little_endian(self) -> u8 {
self.0.to_le()
}
#[inline]
#[allow(clippy::wrong_self_convention)]
fn from_little_endian(v: u8) -> Self {
let b = u8::from_le(v);
Self(b)
}
}
impl<'a> ::flatbuffers::Verifiable for Equipment {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
u8::run_verifier(v, pos)
}
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
u8::run_verifier(v, pos)
}
}
impl ::flatbuffers::SimpleToVerifyInSlice for Equipment {}
pub struct EquipmentUnionTableOffset {}
#[allow(clippy::upper_case_acronyms)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum EquipmentT {
NONE,
Weapon(alloc::boxed::Box<WeaponT>),
NONE,
Weapon(alloc::boxed::Box<WeaponT>),
}
impl Default for EquipmentT {
fn default() -> Self {
Self::NONE
}
fn default() -> Self {
Self::NONE
}
}
impl EquipmentT {
pub fn equipment_type(&self) -> Equipment {
match self {
Self::NONE => Equipment::NONE,
Self::Weapon(_) => Equipment::Weapon,
pub fn equipment_type(&self) -> Equipment {
match self {
Self::NONE => Equipment::NONE,
Self::Weapon(_) => Equipment::Weapon,
}
}
}
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(&self, fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>) -> Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>> {
match self {
Self::NONE => None,
Self::Weapon(v) => Some(v.pack(fbb).as_union_value()),
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(&self, fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>) -> Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>> {
match self {
Self::NONE => None,
Self::Weapon(v) => Some(v.pack(fbb).as_union_value()),
}
}
}
/// If the union variant matches, return the owned WeaponT, setting the union to NONE.
pub fn take_weapon(&mut self) -> Option<alloc::boxed::Box<WeaponT>> {
if let Self::Weapon(_) = self {
let v = ::core::mem::replace(self, Self::NONE);
if let Self::Weapon(w) = v {
Some(w)
} else {
unreachable!()
}
} else {
None
/// If the union variant matches, return the owned WeaponT, setting the union to NONE.
pub fn take_weapon(&mut self) -> Option<alloc::boxed::Box<WeaponT>> {
if let Self::Weapon(_) = self {
let v = ::core::mem::replace(self, Self::NONE);
if let Self::Weapon(w) = v {
Some(w)
} else {
unreachable!()
}
} else {
None
}
}
/// If the union variant matches, return a reference to the WeaponT.
pub fn as_weapon(&self) -> Option<&WeaponT> {
if let Self::Weapon(v) = self { Some(v.as_ref()) } else { None }
}
/// If the union variant matches, return a mutable reference to the WeaponT.
pub fn as_weapon_mut(&mut self) -> Option<&mut WeaponT> {
if let Self::Weapon(v) = self { Some(v.as_mut()) } else { None }
}
}
/// If the union variant matches, return a reference to the WeaponT.
pub fn as_weapon(&self) -> Option<&WeaponT> {
if let Self::Weapon(v) = self { Some(v.as_ref()) } else { None }
}
/// If the union variant matches, return a mutable reference to the WeaponT.
pub fn as_weapon_mut(&mut self) -> Option<&mut WeaponT> {
if let Self::Weapon(v) = self { Some(v.as_mut()) } else { None }
}
}
@@ -2,212 +2,225 @@
// @generated
extern crate alloc;
use super::*;
pub enum MonsterOffset {}
#[derive(Copy, Clone, PartialEq)]
pub enum MonsterOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct Monster<'a> {
pub _tab: ::flatbuffers::Table<'a>,
pub _tab: ::flatbuffers::Table<'a>,
}
impl<'a> ::flatbuffers::Follow<'a> for Monster<'a> {
type Inner = Monster<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
type Inner = Monster<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
impl<'a> Monster<'a> {
pub const VT_POS: ::flatbuffers::VOffsetT = 4;
pub const VT_MANA: ::flatbuffers::VOffsetT = 6;
pub const VT_HP: ::flatbuffers::VOffsetT = 8;
pub const VT_NAME: ::flatbuffers::VOffsetT = 10;
pub const VT_INVENTORY: ::flatbuffers::VOffsetT = 14;
pub const VT_COLOR: ::flatbuffers::VOffsetT = 16;
pub const VT_WEAPONS: ::flatbuffers::VOffsetT = 18;
pub const VT_EQUIPPED_TYPE: ::flatbuffers::VOffsetT = 20;
pub const VT_EQUIPPED: ::flatbuffers::VOffsetT = 22;
pub const VT_PATH: ::flatbuffers::VOffsetT = 24;
pub const VT_POS: ::flatbuffers::VOffsetT = 4;
pub const VT_MANA: ::flatbuffers::VOffsetT = 6;
pub const VT_HP: ::flatbuffers::VOffsetT = 8;
pub const VT_NAME: ::flatbuffers::VOffsetT = 10;
pub const VT_INVENTORY: ::flatbuffers::VOffsetT = 14;
pub const VT_COLOR: ::flatbuffers::VOffsetT = 16;
pub const VT_WEAPONS: ::flatbuffers::VOffsetT = 18;
pub const VT_EQUIPPED_TYPE: ::flatbuffers::VOffsetT = 20;
pub const VT_EQUIPPED: ::flatbuffers::VOffsetT = 22;
pub const VT_PATH: ::flatbuffers::VOffsetT = 24;
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Monster"
}
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Monster { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args MonsterArgs<'args>
) -> ::flatbuffers::WIPOffset<Monster<'bldr>> {
let mut builder = MonsterBuilder::new(_fbb);
if let Some(x) = args.path { builder.add_path(x); }
if let Some(x) = args.equipped { builder.add_equipped(x); }
if let Some(x) = args.weapons { builder.add_weapons(x); }
if let Some(x) = args.inventory { builder.add_inventory(x); }
if let Some(x) = args.name { builder.add_name(x); }
if let Some(x) = args.pos { builder.add_pos(x); }
builder.add_hp(args.hp);
builder.add_mana(args.mana);
builder.add_equipped_type(args.equipped_type);
builder.add_color(args.color);
builder.finish()
}
pub fn unpack(&self) -> MonsterT {
let pos = self.pos().map(|x| {
x.unpack()
});
let mana = self.mana();
let hp = self.hp();
let name = self.name().map(|x| {
alloc::string::ToString::to_string(x)
});
let inventory = self.inventory().map(|x| {
x.into_iter().collect()
});
let color = self.color();
let weapons = self.weapons().map(|x| {
x.iter().map(|t| t.unpack()).collect()
});
let equipped = match self.equipped_type() {
Equipment::NONE => EquipmentT::NONE,
Equipment::Weapon => EquipmentT::Weapon(alloc::boxed::Box::new(
self.equipped_as_weapon()
.expect("Invalid union table, expected `Equipment::Weapon`.")
.unpack()
)),
_ => EquipmentT::NONE,
};
let path = self.path().map(|x| {
x.iter().map(|t| t.unpack()).collect()
});
MonsterT {
pos,
mana,
hp,
name,
inventory,
color,
weapons,
equipped,
path,
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Monster"
}
}
#[inline]
pub fn pos(&self) -> Option<&'a Vec3> {
// 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 {
// 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 {
// 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> {
// 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<::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 {
// 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>>>> {
// 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 {
// 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>> {
// 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<::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(|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
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Monster { _tab: table }
}
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args MonsterArgs<'args>
) -> ::flatbuffers::WIPOffset<Monster<'bldr>> {
let mut builder = MonsterBuilder::new(_fbb);
if let Some(x) = args.path { builder.add_path(x); }
if let Some(x) = args.equipped { builder.add_equipped(x); }
if let Some(x) = args.weapons { builder.add_weapons(x); }
if let Some(x) = args.inventory { builder.add_inventory(x); }
if let Some(x) = args.name { builder.add_name(x); }
if let Some(x) = args.pos { builder.add_pos(x); }
builder.add_hp(args.hp);
builder.add_mana(args.mana);
builder.add_equipped_type(args.equipped_type);
builder.add_color(args.color);
builder.finish()
}
pub fn unpack(&self) -> MonsterT {
let pos = self.pos().map(|x| {
x.unpack()
});
let mana = self.mana();
let hp = self.hp();
let name = self.name().map(|x| {
alloc::string::ToString::to_string(x)
});
let inventory = self.inventory().map(|x| {
x.into_iter().collect()
});
let color = self.color();
let weapons = self.weapons().map(|x| {
x.iter().map(|t| t.unpack()).collect()
});
let equipped = match self.equipped_type() {
Equipment::NONE => EquipmentT::NONE,
Equipment::Weapon => EquipmentT::Weapon(alloc::boxed::Box::new(
self.equipped_as_weapon()
.expect("Invalid union table, expected `Equipment::Weapon`.")
.unpack()
)),
_ => EquipmentT::NONE,
};
let path = self.path().map(|x| {
x.iter().map(|t| t.unpack()).collect()
});
MonsterT {
pos,
mana,
hp,
name,
inventory,
color,
weapons,
equipped,
path,
}
}
#[inline]
pub fn pos(&self) -> Option<&'a Vec3> {
// 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 {
// 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 {
// 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> {
// 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<::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 {
// 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>>>> {
// 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 {
// 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>> {
// 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<::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(|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
}
}
}
impl ::flatbuffers::Verifiable for Monster<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<Vec3>("pos", Self::VT_POS, false)?
.visit_field::<i16>("mana", Self::VT_MANA, false)?
.visit_field::<i16>("hp", Self::VT_HP, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, u8>>>("inventory", Self::VT_INVENTORY, false)?
.visit_field::<Color>("color", Self::VT_COLOR, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Weapon>>>>("weapons", Self::VT_WEAPONS, false)?
.visit_union::<Equipment, _>("equipped_type", Self::VT_EQUIPPED_TYPE, "equipped", Self::VT_EQUIPPED, false, |key, v, pos| {
match key {
Equipment::Weapon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos),
_ => Ok(()),
}
})?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, Vec3>>>("path", Self::VT_PATH, false)?
.finish();
Ok(())
}
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<Vec3>("pos", Self::VT_POS, false)?
.visit_field::<i16>("mana", Self::VT_MANA, false)?
.visit_field::<i16>("hp", Self::VT_HP, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, u8>>>("inventory", Self::VT_INVENTORY, false)?
.visit_field::<Color>("color", Self::VT_COLOR, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Weapon>>>>("weapons", Self::VT_WEAPONS, false)?
.visit_union::<Equipment, _>("equipped_type", Self::VT_EQUIPPED_TYPE, "equipped", Self::VT_EQUIPPED, false, |key, v, pos| {
match key {
Equipment::Weapon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos),
_ => Ok(()),
}
})?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, Vec3>>>("path", Self::VT_PATH, false)?
.finish();
Ok(())
}
}
pub struct MonsterArgs<'a> {
pub pos: Option<&'a Vec3>,
pub mana: i16,
@@ -220,246 +233,273 @@ pub struct MonsterArgs<'a> {
pub equipped: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>,
pub path: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, Vec3>>>,
}
impl<'a> Default for MonsterArgs<'a> {
#[inline]
fn default() -> Self {
MonsterArgs {
pos: None,
mana: 150,
hp: 100,
name: None,
inventory: None,
color: Color::Blue,
weapons: None,
equipped_type: Equipment::NONE,
equipped: None,
path: None,
#[inline]
fn default() -> Self {
MonsterArgs {
pos: None,
mana: 150,
hp: 100,
name: None,
inventory: None,
color: Color::Blue,
weapons: None,
equipped_type: Equipment::NONE,
equipped: None,
path: None,
}
}
}
}
pub struct MonsterBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> MonsterBuilder<'a, 'b, A> {
#[inline]
pub fn add_pos(&mut self, pos: &Vec3) {
self.fbb_.push_slot_always::<&Vec3>(Monster::VT_POS, pos);
}
#[inline]
pub fn add_mana(&mut self, mana: i16) {
self.fbb_.push_slot::<i16>(Monster::VT_MANA, mana, 150);
}
#[inline]
pub fn add_hp(&mut self, hp: i16) {
self.fbb_.push_slot::<i16>(Monster::VT_HP, hp, 100);
}
#[inline]
pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_NAME, name);
}
#[inline]
pub fn add_inventory(&mut self, inventory: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , u8>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_INVENTORY, inventory);
}
#[inline]
pub fn add_color(&mut self, color: Color) {
self.fbb_.push_slot::<Color>(Monster::VT_COLOR, color, Color::Blue);
}
#[inline]
pub fn add_weapons(&mut self, weapons: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset<Weapon<'b >>>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_WEAPONS, weapons);
}
#[inline]
pub fn add_equipped_type(&mut self, equipped_type: Equipment) {
self.fbb_.push_slot::<Equipment>(Monster::VT_EQUIPPED_TYPE, equipped_type, Equipment::NONE);
}
#[inline]
pub fn add_equipped(&mut self, equipped: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_EQUIPPED, equipped);
}
#[inline]
pub fn add_path(&mut self, path: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , Vec3>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_PATH, path);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> MonsterBuilder<'a, 'b, A> {
let start = _fbb.start_table();
MonsterBuilder {
fbb_: _fbb,
start_: start,
#[inline]
pub fn add_pos(&mut self, pos: &Vec3) {
self.fbb_.push_slot_always::<&Vec3>(Monster::VT_POS, pos);
}
#[inline]
pub fn add_mana(&mut self, mana: i16) {
self.fbb_.push_slot::<i16>(Monster::VT_MANA, mana, 150);
}
#[inline]
pub fn add_hp(&mut self, hp: i16) {
self.fbb_.push_slot::<i16>(Monster::VT_HP, hp, 100);
}
#[inline]
pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_NAME, name);
}
#[inline]
pub fn add_inventory(&mut self, inventory: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , u8>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_INVENTORY, inventory);
}
#[inline]
pub fn add_color(&mut self, color: Color) {
self.fbb_.push_slot::<Color>(Monster::VT_COLOR, color, Color::Blue);
}
#[inline]
pub fn add_weapons(&mut self, weapons: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset<Weapon<'b >>>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_WEAPONS, weapons);
}
#[inline]
pub fn add_equipped_type(&mut self, equipped_type: Equipment) {
self.fbb_.push_slot::<Equipment>(Monster::VT_EQUIPPED_TYPE, equipped_type, Equipment::NONE);
}
#[inline]
pub fn add_equipped(&mut self, equipped: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_EQUIPPED, equipped);
}
#[inline]
pub fn add_path(&mut self, path: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , Vec3>>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_PATH, path);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> MonsterBuilder<'a, 'b, A> {
let start = _fbb.start_table();
MonsterBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Monster<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Monster<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
impl ::core::fmt::Debug for Monster<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Monster");
ds.field("pos", &self.pos());
ds.field("mana", &self.mana());
ds.field("hp", &self.hp());
ds.field("name", &self.name());
ds.field("inventory", &self.inventory());
ds.field("color", &self.color());
ds.field("weapons", &self.weapons());
ds.field("equipped_type", &self.equipped_type());
match self.equipped_type() {
Equipment::Weapon => {
if let Some(x) = self.equipped_as_weapon() {
ds.field("equipped", &x)
} else {
ds.field("equipped", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("equipped", &x)
},
};
ds.field("path", &self.path());
ds.finish()
}
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Monster");
ds.field("pos", &self.pos());
ds.field("mana", &self.mana());
ds.field("hp", &self.hp());
ds.field("name", &self.name());
ds.field("inventory", &self.inventory());
ds.field("color", &self.color());
ds.field("weapons", &self.weapons());
ds.field("equipped_type", &self.equipped_type());
match self.equipped_type() {
Equipment::Weapon => {
if let Some(x) = self.equipped_as_weapon() {
ds.field("equipped", &x)
} else {
ds.field("equipped", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("equipped", &x)
},
};
ds.field("path", &self.path());
ds.finish()
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub struct MonsterT {
pub pos: Option<Vec3T>,
pub mana: i16,
pub hp: i16,
pub name: Option<alloc::string::String>,
pub inventory: Option<alloc::vec::Vec<u8>>,
pub color: Color,
pub weapons: Option<alloc::vec::Vec<WeaponT>>,
pub equipped: EquipmentT,
pub path: Option<alloc::vec::Vec<Vec3T>>,
pub pos: Option<Vec3T>,
pub mana: i16,
pub hp: i16,
pub name: Option<alloc::string::String>,
pub inventory: Option<alloc::vec::Vec<u8>>,
pub color: Color,
pub weapons: Option<alloc::vec::Vec<WeaponT>>,
pub equipped: EquipmentT,
pub path: Option<alloc::vec::Vec<Vec3T>>,
}
impl Default for MonsterT {
fn default() -> Self {
Self {
pos: None,
mana: 150,
hp: 100,
name: None,
inventory: None,
color: Color::Blue,
weapons: None,
equipped: EquipmentT::NONE,
path: None,
fn default() -> Self {
Self {
pos: None,
mana: 150,
hp: 100,
name: None,
inventory: None,
color: Color::Blue,
weapons: None,
equipped: EquipmentT::NONE,
path: None,
}
}
}
}
impl MonsterT {
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Monster<'b>> {
let pos_tmp = self.pos.as_ref().map(|x| x.pack());
let pos = pos_tmp.as_ref();
let mana = self.mana;
let hp = self.hp;
let name = self.name.as_ref().map(|x|{
_fbb.create_string(x)
});
let inventory = self.inventory.as_ref().map(|x|{
_fbb.create_vector(x)
});
let color = self.color;
let weapons = self.weapons.as_ref().map(|x|{
let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
});
let equipped_type = self.equipped.equipment_type();
let equipped = self.equipped.pack(_fbb);
let path = self.path.as_ref().map(|x|{
let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
});
Monster::create(_fbb, &MonsterArgs{
pos,
mana,
hp,
name,
inventory,
color,
weapons,
equipped_type,
equipped,
path,
})
}
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Monster<'b>> {
let pos_tmp = self.pos.as_ref().map(|x| x.pack());
let pos = pos_tmp.as_ref();
let mana = self.mana;
let hp = self.hp;
let name = self.name.as_ref().map(|x|{
_fbb.create_string(x)
});
let inventory = self.inventory.as_ref().map(|x|{
_fbb.create_vector(x)
});
let color = self.color;
let weapons = self.weapons.as_ref().map(|x|{
let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
});
let equipped_type = self.equipped.equipment_type();
let equipped = self.equipped.pack(_fbb);
let path = self.path.as_ref().map(|x|{
let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
});
Monster::create(_fbb, &MonsterArgs{
pos,
mana,
hp,
name,
inventory,
color,
weapons,
equipped_type,
equipped,
path,
})
}
}
#[inline]
/// Verifies that a buffer of bytes contains a `Monster`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root::<Monster>(buf)
}
#[inline]
pub fn root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root::<Monster>(buf)
}
/// Verifies that a buffer of bytes contains a size prefixed
/// `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root::<Monster>(buf)
}
#[inline]
pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root::<Monster>(buf)
}
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
pub fn root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root_with_opts::<Monster<'b>>(opts, buf)
}
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Monster` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf)
}
/// Assumes, without verification, that a buffer of bytes contains a Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Monster`.
pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::root_unchecked::<Monster>(buf) }
}
#[inline]
pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::root_unchecked::<Monster>(buf) }
}
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`.
pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Monster>(buf) }
}
#[inline]
pub fn finish_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Monster<'a>>) {
fbb.finish(root, None);
pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Monster>(buf) }
}
#[inline]
pub fn finish_size_prefixed_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, root: ::flatbuffers::WIPOffset<Monster<'a>>) {
fbb.finish_size_prefixed(root, None);
pub fn finish_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Monster<'a>>
) {
fbb.finish(root, None);
}
#[inline]
pub fn finish_size_prefixed_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Monster<'a>>
) {
fbb.finish_size_prefixed(root, None);
}
@@ -2,47 +2,57 @@
// @generated
extern crate alloc;
use super::*;
// struct Vec3, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
pub struct Vec3(pub [u8; 12]);
impl Default for Vec3 {
fn default() -> Self {
Self([0; 12])
}
impl Default for Vec3 {
fn default() -> Self {
Self([0; 12])
}
}
impl ::core::fmt::Debug for Vec3 {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
f.debug_struct("Vec3")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
f.debug_struct("Vec3")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
}
impl ::flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl<'a> ::flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { <&'a Vec3>::follow(buf, loc) }
}
type Inner = &'a Vec3;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { <&'a Vec3>::follow(buf, loc) }
}
}
impl<'a> ::flatbuffers::Follow<'a> for &'a Vec3 {
type Inner = &'a Vec3;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { ::flatbuffers::follow_cast_ref::<Vec3>(buf, loc) }
}
type Inner = &'a Vec3;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe { ::flatbuffers::follow_cast_ref::<Vec3>(buf, loc) }
}
}
impl<'b> ::flatbuffers::Push for Vec3 {
type Output = Vec3;
#[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
let src = unsafe { ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, <Self as ::flatbuffers::Push>::size()) };
dst.copy_from_slice(src);
}
#[inline]
fn alignment() -> ::flatbuffers::PushAlignment {
::flatbuffers::PushAlignment::new(4)
@@ -50,141 +60,150 @@ impl<'b> ::flatbuffers::Push for Vec3 {
}
impl<'a> ::flatbuffers::Verifiable for Vec3 {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.in_buffer::<Self>(pos)
}
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.in_buffer::<Self>(pos)
}
}
impl<'a> Vec3 {
#[allow(clippy::too_many_arguments)]
pub fn new(
x: f32,
y: f32,
z: f32,
) -> Self {
let mut s = Self([0; 12]);
s.set_x(x);
s.set_y(y);
s.set_z(z);
s
}
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Vec3"
}
pub fn x(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[0..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
pub fn set_x(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[0..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
#[allow(clippy::too_many_arguments)]
pub fn new(
x: f32,
y: f32,
z: f32,
) -> Self {
let mut s = Self([0; 12]);
s.set_x(x);
s.set_y(y);
s.set_z(z);
s
}
}
pub fn y(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[4..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
pub fn set_y(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[4..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Vec3"
}
}
pub fn z(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[8..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
pub fn set_z(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[8..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
pub fn x(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[0..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
}
pub fn unpack(&self) -> Vec3T {
Vec3T {
x: self.x(),
y: self.y(),
z: self.z(),
pub fn set_x(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[0..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
}
}
pub fn y(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[4..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
pub fn set_y(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[4..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
}
}
pub fn z(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping(
self.0[8..].as_ptr(),
mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
mem.assume_init()
})
}
pub fn set_z(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety:
// Created from a valid Table for this object
// Which contains a valid value in this slot
unsafe {
::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8,
self.0[8..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
);
}
}
pub fn unpack(&self) -> Vec3T {
Vec3T {
x: self.x(),
y: self.y(),
z: self.z(),
}
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, PartialEq)]
pub struct Vec3T {
pub x: f32,
pub y: f32,
pub z: f32,
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Vec3T {
pub fn pack(&self) -> Vec3 {
Vec3::new(
self.x,
self.y,
self.z,
)
}
impl Default for Vec3T {
fn default() -> Self {
Self {
x: 0.0,
y: 0.0,
z: 0.0,
}
}
}
impl Vec3T {
pub fn pack(&self) -> Vec3 {
Vec3::new(
self.x,
self.y,
self.z,
)
}
}
@@ -2,159 +2,172 @@
// @generated
extern crate alloc;
use super::*;
pub enum WeaponOffset {}
#[derive(Copy, Clone, PartialEq)]
pub enum WeaponOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct Weapon<'a> {
pub _tab: ::flatbuffers::Table<'a>,
pub _tab: ::flatbuffers::Table<'a>,
}
impl<'a> ::flatbuffers::Follow<'a> for Weapon<'a> {
type Inner = Weapon<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
type Inner = Weapon<'a>;
#[inline]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
impl<'a> Weapon<'a> {
pub const VT_NAME: ::flatbuffers::VOffsetT = 4;
pub const VT_DAMAGE: ::flatbuffers::VOffsetT = 6;
pub const VT_NAME: ::flatbuffers::VOffsetT = 4;
pub const VT_DAMAGE: ::flatbuffers::VOffsetT = 6;
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Weapon"
}
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Weapon { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args WeaponArgs<'args>
) -> ::flatbuffers::WIPOffset<Weapon<'bldr>> {
let mut builder = WeaponBuilder::new(_fbb);
if let Some(x) = args.name { builder.add_name(x); }
builder.add_damage(args.damage);
builder.finish()
}
pub fn unpack(&self) -> WeaponT {
let name = self.name().map(|x| {
alloc::string::ToString::to_string(x)
});
let damage = self.damage();
WeaponT {
name,
damage,
pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Weapon"
}
}
#[inline]
pub fn name(&self) -> Option<&'a str> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(Weapon::VT_NAME, None)}
}
#[inline]
pub fn damage(&self) -> i16 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i16>(Weapon::VT_DAMAGE, Some(0)).unwrap()}
}
#[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Weapon { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
args: &'args WeaponArgs<'args>
) -> ::flatbuffers::WIPOffset<Weapon<'bldr>> {
let mut builder = WeaponBuilder::new(_fbb);
if let Some(x) = args.name { builder.add_name(x); }
builder.add_damage(args.damage);
builder.finish()
}
pub fn unpack(&self) -> WeaponT {
let name = self.name().map(|x| {
alloc::string::ToString::to_string(x)
});
let damage = self.damage();
WeaponT {
name,
damage,
}
}
#[inline]
pub fn name(&self) -> Option<&'a str> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(Weapon::VT_NAME, None)}
}
#[inline]
pub fn damage(&self) -> i16 {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<i16>(Weapon::VT_DAMAGE, Some(0)).unwrap()}
}
}
impl ::flatbuffers::Verifiable for Weapon<'_> {
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
.visit_field::<i16>("damage", Self::VT_DAMAGE, false)?
.finish();
Ok(())
}
#[inline]
fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
.visit_field::<i16>("damage", Self::VT_DAMAGE, false)?
.finish();
Ok(())
}
}
pub struct WeaponArgs<'a> {
pub name: Option<::flatbuffers::WIPOffset<&'a str>>,
pub damage: i16,
}
impl<'a> Default for WeaponArgs<'a> {
#[inline]
fn default() -> Self {
WeaponArgs {
name: None,
damage: 0,
#[inline]
fn default() -> Self {
WeaponArgs {
name: None,
damage: 0,
}
}
}
}
pub struct WeaponBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> WeaponBuilder<'a, 'b, A> {
#[inline]
pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Weapon::VT_NAME, name);
}
#[inline]
pub fn add_damage(&mut self, damage: i16) {
self.fbb_.push_slot::<i16>(Weapon::VT_DAMAGE, damage, 0);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> WeaponBuilder<'a, 'b, A> {
let start = _fbb.start_table();
WeaponBuilder {
fbb_: _fbb,
start_: start,
#[inline]
pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Weapon::VT_NAME, name);
}
#[inline]
pub fn add_damage(&mut self, damage: i16) {
self.fbb_.push_slot::<i16>(Weapon::VT_DAMAGE, damage, 0);
}
#[inline]
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> WeaponBuilder<'a, 'b, A> {
let start = _fbb.start_table();
WeaponBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Weapon<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
#[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Weapon<'a>> {
let o = self.fbb_.end_table(self.start_);
::flatbuffers::WIPOffset::new(o.value())
}
}
impl ::core::fmt::Debug for Weapon<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Weapon");
ds.field("name", &self.name());
ds.field("damage", &self.damage());
ds.finish()
}
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Weapon");
ds.field("name", &self.name());
ds.field("damage", &self.damage());
ds.finish()
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub struct WeaponT {
pub name: Option<alloc::string::String>,
pub damage: i16,
pub name: Option<alloc::string::String>,
pub damage: i16,
}
impl Default for WeaponT {
fn default() -> Self {
Self {
name: None,
damage: 0,
fn default() -> Self {
Self {
name: None,
damage: 0,
}
}
}
}
impl WeaponT {
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Weapon<'b>> {
let name = self.name.as_ref().map(|x|{
_fbb.create_string(x)
});
let damage = self.damage;
Weapon::create(_fbb, &WeaponArgs{
name,
damage,
})
}
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Weapon<'b>> {
let name = self.name.as_ref().map(|x|{
_fbb.create_string(x)
});
let damage = self.damage;
Weapon::create(_fbb, &WeaponArgs{
name,
damage,
})
}
}
+17 -15
View File
@@ -251,21 +251,6 @@ flatc(
schema="vector_table_naked_ptr.fbs",
)
flatc(
[
"--cpp",
"--gen-compare",
"--gen-mutable",
"--gen-object-api",
"--reflect-names",
"--cpp-include",
"test_vector_type.h",
"--cpp-vector-type",
"::flatbuffers::tests::CustomVector",
],
schema="cpp_vector_type.fbs",
)
flatc(
BASE_OPTS + CPP_OPTS + CS_OPTS + JAVA_OPTS + KOTLIN_OPTS + PHP_OPTS,
prefix="union_vector",
@@ -409,6 +394,11 @@ flatc(
schema="native_inline_table_test.fbs",
)
flatc(
["--cpp", "--gen-compare", "--gen-mutable", "--gen-object-api", "--reflect-names"],
schema="cross_namespace_pack_test.fbs",
)
flatc(
RUST_OPTS,
prefix="arrays_test",
@@ -432,6 +422,11 @@ flatc(
schema="nested_union_test.fbs",
)
flatc(
["--python", "--gen-object-api"],
schema="union_name_test.fbs",
)
flatc(
NO_INCL_OPTS + CPP_OPTS,
schema="default_vectors_strings_test.fbs",
@@ -532,6 +527,13 @@ flatc(
cwd=swift_code_gen,
)
flatc(
SWIFT_OPTS_CODE_GEN + BASE_OPTS,
schema="empty_vtable.fbs",
cwd=swift_code_gen,
prefix="../../Tests/Flatbuffers/",
)
# Swift Wasm Tests
swift_Wasm_prefix = "swift/Wasm.tests/Tests/FlatBuffers.Test.Swift.WasmTests"
flatc(
+3 -2
View File
@@ -20,6 +20,7 @@ from util import flatc, root_path
grpc_examples_path = Path(root_path, "grpc/examples")
greeter_schema = str(Path(grpc_examples_path, "greeter.fbs"))
greeter_schema_v2 = str(Path(grpc_examples_path, "greeter_v2.fbs"))
COMMON_ARGS = [
"--grpc",
@@ -54,8 +55,8 @@ def GenerateGRPCExamples():
"--swift",
"--gen-json-emit",
],
schema=greeter_schema,
cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Model"),
schema=greeter_schema_v2,
cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Models"),
)
flatc(
+1 -3
View File
@@ -126,9 +126,7 @@ static BinarySection GenerateMissingSection(const uint64_t offset,
std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
if (bfbs_ != nullptr && bfbs_length_ != 0) {
flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
if ((is_size_prefixed_ &&
!reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
!reflection::VerifySchemaBuffer(verifier)) {
if (!reflection::VerifySchemaBuffer(verifier)) {
return {};
}
}
-9
View File
@@ -145,12 +145,6 @@ const static FlatCOption flatc_options[] = {
{"", "cpp-str-flex-ctor", "",
"Don't construct custom string types by passing std::string from "
"Flatbuffers, but (char* + length)."},
{"", "cpp-vector-type", "T",
"Set object API vector type (default std::vector). T must be a "
"template taking a single element type argument and support "
"resize(), reserve(), size(), data(), operator[], emplace_back(), and "
"begin()/end(). The custom type also needs its own header to be "
"included via --cpp-include."},
{"", "cpp-field-case-style", "STYLE",
"Generate C++ fields using selected case style. Supported STYLE values: * "
"'unchanged' - leave unchanged (default) * 'upper' - schema snake_case "
@@ -551,9 +545,6 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--cpp-str-flex-ctor") {
opts.cpp_object_api_string_flexible_constructor = true;
} else if (arg == "--cpp-vector-type") {
if (++argi >= argc) Error("missing type following: " + arg, true);
opts.cpp_object_api_vector_type = argv[argi];
} else if (arg == "--no-cpp-direct-copy") {
opts.cpp_direct_copy = false;
} else if (arg == "--cpp-field-case-style") {
+47 -298
View File
@@ -257,19 +257,6 @@ class CppGenerator : public BaseGenerator {
code_ += " FLATBUFFERS_VERSION_REVISION == " +
std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
code_ += " \"Non-compatible flatbuffers version included\");";
code_ += "// Ensure the included flatbuffers.h is Bigfoot's fork - stock";
code_ += "// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.";
code_ += "#ifndef FLATBUFFERS_BIGFOOT_VERSION";
code_ +=
"#error \"This file requires Bigfoot's flatbuffers fork - stock "
"flatbuffers is not compatible\"";
code_ += "#endif";
code_ += "static_assert(FLATBUFFERS_BIGFOOT_VERSION == " +
std::to_string(FLATBUFFERS_BIGFOOT_VERSION) + ",";
code_ +=
" \"Non-compatible Bigfoot flatbuffers fork version "
"included\");";
}
void GenIncludeDependencies() {
@@ -417,7 +404,7 @@ class CppGenerator : public BaseGenerator {
code_ += "struct {{STRUCT_NAME}}BinarySchema {";
code_ += " static const uint8_t *data() {";
code_ += " // Buffer containing the binary schema.";
code_ += " static const uint8_t bfbsData[" +
code_ += " alignas(uint64_t) static const uint8_t bfbsData[" +
NumToString(parser_.builder_.GetSize()) + "] = {";
code_ += binary_schema_hex_text;
code_ += " };";
@@ -542,8 +529,6 @@ class CppGenerator : public BaseGenerator {
code_ += "";
}
GenerateBigfootRefForwardDecls();
// Generate preablmle code for mini reflection.
if (opts_.mini_reflect != IDLOptions::kNone) {
// To break cyclic dependencies, first pre-declare all tables/structs.
@@ -773,8 +758,6 @@ class CppGenerator : public BaseGenerator {
if (cur_name_space_) SetNameSpace(nullptr);
GenerateBigfootRefImpls();
// Close the include guard.
code_ += "#endif // " + include_guard;
@@ -909,24 +892,6 @@ class CppGenerator : public BaseGenerator {
return opts_.gen_nullable ? " _Nullable " : "";
}
// A field's `native_type`/`native_type_pack_name` normally come from the
// referenced struct's own declaration. A field can override both (see
// `bigfoot_ref` in idl_parser.cpp, which synthesizes these two attributes
// directly on the field) to instantiate a templated native type
// differently per field.
static const Value* EffectiveNativeType(const FieldDef& field,
const StructDef& struct_def) {
if (const auto v = field.attributes.Lookup("native_type")) return v;
return struct_def.attributes.Lookup("native_type");
}
static const Value* EffectiveNativeTypePackName(const FieldDef& field,
const StructDef& struct_def) {
if (const auto v = field.attributes.Lookup("native_type_pack_name"))
return v;
return struct_def.attributes.Lookup("native_type_pack_name");
}
static std::string NativeName(const std::string& name, const StructDef* sd,
const IDLOptions& opts) {
// If the table is a native_type, return the native_type name.
@@ -972,23 +937,6 @@ class CppGenerator : public BaseGenerator {
"std::string"; // Only for custom string types.
}
const std::string NativeVectorType(const FieldDef* field) {
auto attr = field ? field->attributes.Lookup("cpp_vector_type") : nullptr;
auto& ret = attr ? attr->constant : opts_.cpp_object_api_vector_type;
if (ret.empty()) {
return "std::vector";
}
return ret;
}
// True if this field's native vector uses a custom (non-std::vector)
// container, meaning generated Pack() code can't rely on the std::vector
// specific CreateVector*() overloads and must fall back to data()/size()
// or per-element construction instead.
bool UsesCustomVectorType(const FieldDef* field) {
return NativeVectorType(field) != "std::vector";
}
std::string GenTypeNativePtr(const std::string& type, const FieldDef* field,
bool is_constructor) {
auto& ptr_type = PtrType(field);
@@ -1026,21 +974,20 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field);
const auto vector_type = NativeVectorType(&field);
if (vector_type == "std::vector" && type.struct_def &&
if (type.struct_def &&
type.struct_def->attributes.Lookup("native_custom_alloc")) {
auto native_custom_alloc =
type.struct_def->attributes.Lookup("native_custom_alloc");
return "std::vector<" + type_name + "," +
native_custom_alloc->constant + "<" + type_name + ">>";
} else {
return vector_type + "<" + type_name + ">";
return "std::vector<" + type_name + ">";
}
}
case BASE_TYPE_STRUCT: {
auto type_name = WrapInNameSpace(*type.struct_def);
if (IsStruct(type)) {
auto native_type = EffectiveNativeType(field, *type.struct_def);
auto native_type = type.struct_def->attributes.Lookup("native_type");
if (native_type) {
type_name = native_type->constant;
}
@@ -2032,7 +1979,7 @@ class CppGenerator : public BaseGenerator {
const std::string& full_type =
(cpp_type
? (IsVector(field.value.type)
? NativeVectorType(&field) + "<" +
? "std::vector<" +
GenTypeNativePtr(cpp_type->constant, &field,
false) +
"> "
@@ -2049,19 +1996,8 @@ class CppGenerator : public BaseGenerator {
" = " + (native_default ? std::string(native_default->constant)
: GetDefaultScalarValue(field, true));
} else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
if (IsStruct(field.value.type)) {
if (native_default) {
field_di = " = " + native_default->constant;
}
} else if (!cpp_type && !field.native_inline && field.IsRequired() &&
PtrType(&field) != "naked") {
// A required table field can never legally be absent once
// Verify()/Pack() succeed, so default-construct it here instead
// of leaving every hand-written native constructor to remember
// to allocate it before the first Pack().
const auto nn = WrapNativeNameInNameSpace(
*field.value.type.struct_def, opts_);
field_di = "{new " + nn + "()}";
if (IsStruct(field.value.type) && native_default) {
field_di = " = " + native_default->constant;
}
}
}
@@ -2843,15 +2779,17 @@ class CppGenerator : public BaseGenerator {
get_call += ">(" + offset_str + ");";
code_ += get_call;
} else if (IsString(type) && field.value.constant != "0") {
// TODO: Add logic to always convert the string to a valid C++ string
// literal by handling string escapes.
std::string escaped;
flatbuffers::EscapeString(field.value.constant.c_str(),
field.value.constant.length(), &escaped,
true, false);
code_ += " auto* ptr = {{FIELD_VALUE}};";
code_ += " if (ptr) return ptr;";
code_ += " static const struct { uint32_t len; const char s[" +
NumToString(field.value.constant.length() + 1) +
"]; } bfbs_string = { " +
NumToString(field.value.constant.length()) + ", \"" +
field.value.constant + "\" };";
NumToString(field.value.constant.length()) + ", " +
escaped + " };";
code_ +=
" return reinterpret_cast<const ::flatbuffers::String "
" *>(&bfbs_string);";
@@ -3481,11 +3419,15 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("CREATE_STRING", "CreateSharedString");
}
if (field->value.constant != "0") {
std::string escaped;
flatbuffers::EscapeString(field->value.constant.c_str(),
field->value.constant.length(), &escaped,
true, false);
code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : "
"_fbb.{{CREATE_STRING}}(\"" +
field->value.constant + "\");";
"_fbb.{{CREATE_STRING}}(" +
escaped + ");";
} else {
code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
@@ -3579,11 +3521,11 @@ class CppGenerator : public BaseGenerator {
}
case BASE_TYPE_STRUCT: {
if (IsStruct(type)) {
const auto native_type = EffectiveNativeType(afield, *type.struct_def);
const auto& struct_attrs = type.struct_def->attributes;
const auto native_type = struct_attrs.Lookup("native_type");
if (native_type) {
std::string unpack_call = "::flatbuffers::UnPack";
const auto pack_name =
EffectiveNativeTypePackName(afield, *type.struct_def);
const auto pack_name = struct_attrs.Lookup("native_type_pack_name");
if (pack_name) {
unpack_call += pack_name->constant;
}
@@ -3836,22 +3778,13 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
auto vector_type = field.value.type.VectorType();
// If the field's native container isn't std::vector, the
// std::vector-specific CreateVector*() overloads in
// flatbuffer_builder.h can't be used directly. Fall back to
// data()/size()-based overloads (which only require the container to
// support those, like std::vector does) or, where no such overload
// exists, to the same per-element lambda serialization already used
// above for custom string/table/union element types.
const bool custom_vector = UsesCustomVectorType(&field);
switch (vector_type.base_type) {
case BASE_TYPE_STRING: {
if (!custom_vector && NativeString(&field) == "std::string") {
if (NativeString(&field) == "std::string") {
code += "_fbb.CreateVectorOfStrings(" + value + ")";
} else {
// Use by-function serialization to emulate
// CreateVectorOfStrings(); this works also with non-std strings
// and non-std::vector vector types.
// CreateVectorOfStrings(); this works also with non-std strings.
code +=
"_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::"
"String>>"
@@ -3866,37 +3799,20 @@ class CppGenerator : public BaseGenerator {
}
case BASE_TYPE_STRUCT: {
if (IsStruct(vector_type)) {
const auto native_type =
EffectiveNativeType(field, *field.value.type.struct_def);
const auto& struct_attrs =
field.value.type.struct_def->attributes;
const auto native_type = struct_attrs.Lookup("native_type");
if (native_type) {
code += "_fbb.CreateVectorOfNativeStructs<";
code += WrapInNameSpace(*vector_type.struct_def) + ", " +
native_type->constant + ">";
if (custom_vector) {
code += "(" + value + ".data(), " + value + ".size()";
} else {
code += "(" + value;
}
const auto pack_name = EffectiveNativeTypePackName(
field, *field.value.type.struct_def);
code += "(" + value;
const auto pack_name =
struct_attrs.Lookup("native_type_pack_name");
if (pack_name) {
code += ", ::flatbuffers::Pack" + pack_name->constant;
}
code += ")";
} else if (custom_vector &&
(field.value.type.base_type == BASE_TYPE_VECTOR64 ||
field.offset64)) {
// CreateVectorOfStructs64() (and CreateVectorOfStructs64<V>()
// for offset64) only accept a std::vector; use the
// equivalent explicit-template raw pointer overload instead.
const auto struct_type = WrapInNameSpace(*vector_type.struct_def);
const auto vector_t = field.value.type.base_type ==
BASE_TYPE_VECTOR64
? "::flatbuffers::Vector64"
: "::flatbuffers::Vector";
code += "_fbb.CreateVectorOfStructs<" + struct_type +
", ::flatbuffers::Offset64, " + vector_t + ">(" +
value + ".data(), " + value + ".size())";
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
@@ -3908,18 +3824,16 @@ class CppGenerator : public BaseGenerator {
code += "64<::flatbuffers::Vector>";
}
}
if (custom_vector) {
code += "(" + value + ".data(), " + value + ".size())";
} else {
code += "(" + value + ")";
}
code += "(" + value + ")";
}
} else {
code += "_fbb.CreateVector<::flatbuffers::Offset<";
code += WrapInNameSpace(*vector_type.struct_def) + ">> ";
code += "(" + value + ".size(), ";
code += "[](size_t i, _VectorArgs *__va) { ";
code += "return Create" + vector_type.struct_def->name;
code += "return " +
WrapInNameSpace(vector_type.struct_def->defined_namespace,
"Create" + vector_type.struct_def->name);
code += "(*__va->__fbb, ";
if (field.native_inline) {
code += "&(__va->_" + value + "[i])";
@@ -3931,17 +3845,7 @@ class CppGenerator : public BaseGenerator {
break;
}
case BASE_TYPE_BOOL: {
if (custom_vector) {
// Vectors of bool are always stored on the wire as uint8_t
// (there is no Vector<bool>); CreateVectorScalarCast() does
// the per-element bool->uint8_t cast from a raw data()/size()
// pointer pair, avoiding any dependency on std::vector<bool>'s
// bit-packed specialization.
code += "_fbb.CreateVectorScalarCast<uint8_t>(" + value +
".data(), " + value + ".size())";
} else {
code += "_fbb.CreateVector(" + value + ")";
}
code += "_fbb.CreateVector(" + value + ")";
break;
}
case BASE_TYPE_UNION: {
@@ -3977,11 +3881,9 @@ class CppGenerator : public BaseGenerator {
// the underlying storage type (eg. uint8_t).
const auto basetype = GenTypeBasic(
field.value.type.enum_def->underlying_type, false);
const std::string data_ptr =
custom_vector ? value + ".data()"
: "::flatbuffers::data(" + value + ")";
code += "_fbb.CreateVectorScalarCast<" + basetype + ">(" +
data_ptr + ", " + value + ".size())";
code += "_fbb.CreateVectorScalarCast<" + basetype +
">(::flatbuffers::data(" + value + "), " + value +
".size())";
} else if (field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(vector_type, false);
code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
@@ -3990,27 +3892,6 @@ class CppGenerator : public BaseGenerator {
code += "static_cast<" + type + ">((*__va->__rehasher)";
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
code += "; }, &_va )";
} else if (custom_vector) {
// Explicitly specify the element type so it can be deduced
// from a raw data()/size() pointer pair instead of relying on
// the std::vector<T, Alloc>-specific CreateVector overloads.
// Use the user-facing type (matches what GenTypeNative()
// stores in the native vector, e.g. the enum type itself for
// scoped-enum fields) so it matches data()'s pointee type.
auto type = GenTypeBasic(vector_type, true);
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "_fbb.CreateVector<" + type +
", ::flatbuffers::Offset64, ::flatbuffers::Vector64>(" +
value + ".data(), " + value + ".size())";
} else if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "_fbb.CreateVector<" + type +
", ::flatbuffers::Offset64, ::flatbuffers::Vector>(" +
value + ".data(), " + value + ".size())";
} else {
code += "_fbb.CreateVector(" + value + ".data(), " + value +
".size())";
}
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
@@ -4044,12 +3925,12 @@ class CppGenerator : public BaseGenerator {
}
case BASE_TYPE_STRUCT: {
if (IsStruct(field.value.type)) {
const auto native_type =
EffectiveNativeType(field, *field.value.type.struct_def);
const auto& struct_attribs = field.value.type.struct_def->attributes;
const auto native_type = struct_attribs.Lookup("native_type");
if (native_type && field.native_inline) {
code += "::flatbuffers::Pack";
const auto pack_name =
EffectiveNativeTypePackName(field, *field.value.type.struct_def);
struct_attribs.Lookup("native_type_pack_name");
if (pack_name) {
code += pack_name->constant;
}
@@ -4065,8 +3946,10 @@ class CppGenerator : public BaseGenerator {
}
} else {
// _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
const std::string& type = field.value.type.struct_def->name;
code += value + " ? Create" + type;
const auto& nested_struct = *field.value.type.struct_def;
code += value + " ? " +
WrapInNameSpace(nested_struct.defined_namespace,
"Create" + nested_struct.name);
code += "(_fbb, " + value;
if (!field.native_inline) code += GenPtrGet(field);
code += ", _rehasher) : 0";
@@ -4214,7 +4097,8 @@ class CppGenerator : public BaseGenerator {
if (field->value.type.base_type == BASE_TYPE_STRUCT) {
if (IsStruct(field->value.type)) {
auto native_type =
EffectiveNativeType(*field, *field->value.type.struct_def);
field->value.type.struct_def->attributes.Lookup(
"native_type");
auto native_inline = field->attributes.Lookup("native_inline");
if (native_type) {
pass_by_address = true;
@@ -4569,141 +4453,6 @@ class CppGenerator : public BaseGenerator {
}
}
// Split a "::"-qualified C++ name into namespace components + final name.
static std::vector<std::string> SplitQualifiedName(const std::string& qualified) {
std::vector<std::string> parts;
size_t start = qualified.compare(0, 2, "::") == 0 ? 2 : 0;
for (;;) {
const auto pos = qualified.find("::", start);
if (pos == std::string::npos) {
parts.push_back(qualified.substr(start));
break;
}
parts.push_back(qualified.substr(start, pos - start));
start = pos + 2;
}
return parts;
}
// Bigfoot: for every field annotated `bigfoot_ref: "::Ns::AssetX"` (see
// idl_parser.cpp), forward-declare AssetX plus prototype the Pack/UnPack
// functions for its reference wrapper. Called early (alongside the
// regular struct/table forward declarations), since these prototypes -
// unlike their definitions in GenerateBigfootRefImpls() - only need
// AssetX and the wrapper struct forward-declared, not complete.
void GenerateBigfootRefForwardDecls() {
std::unordered_set<std::string> declared_assets;
for (const auto& struct_def : parser_.structs_.vec) {
if (struct_def->generated) continue;
for (const auto& field : struct_def->fields.vec) {
const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref");
if (!bigfoot_ref) continue;
if (!declared_assets.insert(bigfoot_ref->constant).second) continue;
auto parts = SplitQualifiedName(bigfoot_ref->constant);
const std::string class_name = parts.back();
parts.pop_back();
SetNameSpace(nullptr);
for (const auto& ns_part : parts) code_ += "namespace " + ns_part + " {";
code_ += "class " + class_name + ";";
for (auto it = parts.rbegin(); it != parts.rend(); ++it)
code_ += "} // namespace " + *it;
code_ += "";
}
}
std::unordered_set<std::string> declared_pairs;
bool opened_flatbuffers_ns = false;
for (const auto& struct_def : parser_.structs_.vec) {
if (struct_def->generated) continue;
for (const auto& field : struct_def->fields.vec) {
const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref");
if (!bigfoot_ref) continue;
const auto* pack_name = field->attributes.Lookup("native_type_pack_name");
if (!declared_pairs.insert(pack_name->constant).second) continue;
if (!opened_flatbuffers_ns) {
SetNameSpace(nullptr);
code_ += "namespace flatbuffers {";
opened_flatbuffers_ns = true;
}
const auto* native_type = field->attributes.Lookup("native_type");
const std::string flat_wrapper =
WrapInNameSpace(*field->value.type.struct_def);
code_ += flat_wrapper + " Pack" + pack_name->constant +
"(const " + native_type->constant + "& p_asset);";
code_ += native_type->constant + " UnPack" + pack_name->constant +
"(const " + flat_wrapper + "& p_asset);";
}
}
if (opened_flatbuffers_ns) {
code_ += "} // namespace flatbuffers";
code_ += "";
}
}
// Bigfoot: defines the Pack/UnPack functions prototyped by
// GenerateBigfootRefForwardDecls(). Called late (after every struct/table
// in this file has been fully defined), since a wrapper struct (e.g.
// HardReference/SoftReference) may be defined in this same generated file
// rather than one it includes, and these definitions construct it by
// value - they need it complete, unlike the earlier prototypes.
void GenerateBigfootRefImpls() {
std::unordered_set<std::string> declared_pairs;
bool opened_flatbuffers_ns = false;
for (const auto& struct_def : parser_.structs_.vec) {
if (struct_def->generated) continue;
for (const auto& field : struct_def->fields.vec) {
const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref");
if (!bigfoot_ref) continue;
const auto* pack_name = field->attributes.Lookup("native_type_pack_name");
if (!declared_pairs.insert(pack_name->constant).second) continue;
if (!opened_flatbuffers_ns) {
SetNameSpace(nullptr);
code_ += "namespace flatbuffers {";
opened_flatbuffers_ns = true;
}
const auto* native_type = field->attributes.Lookup("native_type");
const std::string flat_wrapper =
WrapInNameSpace(*field->value.type.struct_def);
// A single translation unit can end up including two different
// generated headers that both reference the same asset type (e.g.
// AssetB references AssetA, and some other TU includes both
// AssetA_generated.hpp and AssetB_generated.hpp directly) - each
// would otherwise emit an identical, independent definition of these
// functions. `inline` only allows identical definitions to repeat
// across *different* translation units, not twice within the same
// one, so guard against that with a plain macro guard.
std::string guard_name = pack_name->constant;
std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(), CharToUpper);
const std::string guard = "FLATBUFFERS_BIGFOOT_REF_" + guard_name;
code_ += "#ifndef " + guard;
code_ += "#define " + guard;
code_ += "inline " + flat_wrapper + " Pack" + pack_name->constant +
"(const " + native_type->constant +
"& p_asset) { return {Pack(p_asset.GetUUID())}; }";
code_ += "inline " + native_type->constant + " UnPack" +
pack_name->constant + "(const " + flat_wrapper +
"& p_asset) { return {UnPack(p_asset.uuid())}; }";
code_ += "#endif // " + guard;
}
}
if (opened_flatbuffers_ns) {
code_ += "} // namespace flatbuffers";
code_ += "";
}
}
// Set up the correct namespace. Only open a namespace if the existing one is
// different (closing/opening only what is necessary).
//
+6 -25
View File
@@ -654,34 +654,15 @@ class DartGenerator : public BaseGenerator {
std::string NamespaceAliasFromUnionType(Namespace* root_namespace,
const Type& type) {
const std::vector<std::string> qualified_name_parts =
type.struct_def->defined_namespace->components;
if (std::equal(root_namespace->components.begin(),
root_namespace->components.end(),
qualified_name_parts.begin())) {
const Namespace& type_namespace = *type.struct_def->defined_namespace;
if (root_namespace->components == type_namespace.components) {
return namer_.Type(*type.struct_def);
}
std::string ns;
for (auto it = qualified_name_parts.begin();
it != qualified_name_parts.end(); ++it) {
auto& part = *it;
for (size_t i = 0; i < part.length(); i++) {
if (i && !isdigit(part[i]) && part[i] == CharToUpper(part[i])) {
ns += "_";
ns += CharToLower(part[i]);
} else {
ns += CharToLower(part[i]);
}
}
if (it != qualified_name_parts.end() - 1) {
ns += "_";
}
}
return ns + "." + namer_.Type(*type.struct_def);
const std::string ns = namer_.Namespace(type_namespace);
return ns.empty()
? namer_.Type(*type.struct_def)
: ImportAliasName(ns) + "." + namer_.Type(*type.struct_def);
}
void GenImplementationGetters(
+11 -1
View File
@@ -368,7 +368,17 @@ static std::string GenerateFBS(const Parser& parser,
if (field.value.type.base_type != BASE_TYPE_UTYPE) {
GenComment(field.doc_comment, &schema, nullptr, " ");
schema += " " + field.name + ":" + GenType(field.value.type);
if (field.value.constant != "0") schema += " = " + field.value.constant;
if (field.value.constant != "0") {
if (IsString(field.value.type)) {
std::string escaped;
flatbuffers::EscapeString(field.value.constant.c_str(),
field.value.constant.length(), &escaped,
true, false);
schema += " = " + escaped;
} else {
schema += " = " + field.value.constant;
}
}
std::vector<std::string> attributes;
if (field.IsRequired()) attributes.push_back("required");
if (field.key) attributes.push_back("key");
+5 -5
View File
@@ -1528,7 +1528,7 @@ class PythonGenerator : public BaseGenerator {
} else {
code += "def Create" + field_method + "Vector(builder, data):\n";
}
code += Indent + helper_name + "(builder, data)\n\n";
code += Indent + "return " + helper_name + "(builder, data)\n\n";
}
}
@@ -2095,12 +2095,12 @@ class PythonGenerator : public BaseGenerator {
const auto field_method = namer_.Method(field);
const auto struct_var = namer_.Variable(struct_def);
const EnumDef& enum_def = *field.value.type.enum_def;
auto union_type = namer_.Type(enum_def);
auto union_fn = namer_.Function(enum_def);
if (parser_.opts.include_dependence_headers) {
union_type = namer_.NamespacedType(enum_def) + "." + union_type;
union_fn = namer_.NamespacedType(enum_def) + "." + union_fn;
}
code += GenIndents(2) + "self." + field_field + " = " + union_type +
code += GenIndents(2) + "self." + field_field + " = " + union_fn +
"Creator(" + "self." + field_field + "Type, " + struct_var + "." +
field_method + "())";
}
@@ -2471,7 +2471,7 @@ class PythonGenerator : public BaseGenerator {
} else {
GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
code_prefix += "(self." + field_field + "[i])";
code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
}
}
+552 -414
View File
File diff suppressed because it is too large Load Diff
+83 -49
View File
@@ -164,15 +164,14 @@ class SwiftGenerator : public BaseGenerator {
bool generate() {
code_.Clear();
code_.SetValue("ACCESS", "_accessor");
code_.SetValue("TABLEOFFSET", "VTOFFSET");
code_.SetValue("TABLEOFFSET", "VT");
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
code_ += "// swiftlint:disable all";
code_ += "// swiftformat:disable all\n";
if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
code_.SetValue("IMPLEMENTONLY", parser_.opts.swift_implementation_only
? "@_implementationOnly "
: "");
code_.SetValue("IMPLEMENTONLY",
parser_.opts.swift_implementation_only ? "internal " : "");
code_ += "#if canImport(Common)";
code_ += "{{IMPLEMENTONLY}}import Common";
code_ += "#endif";
@@ -282,9 +281,16 @@ class SwiftGenerator : public BaseGenerator {
NumToString(field.value.type.VectorType().fixed_length);
code_.SetValue("FIXEDLENGTH", fixed_length);
const auto vector_base_type = IsStruct(field.value.type.VectorType())
? (type + "()")
: SwiftConstant(field);
std::string vector_base_type;
if (IsStruct(field.value.type.VectorType())) {
vector_base_type = type + "()";
} else if (IsBool(field.value.type.VectorType().base_type)) {
vector_base_type = "false";
} else if (IsFloat(field.value.type.VectorType().base_type)) {
vector_base_type = "0.0";
} else {
vector_base_type = SwiftConstant(field);
}
code_ += "private var _{{FIELDVAR}}: InlineArray<{{FIXEDLENGTH}}, " +
valueType + ">";
@@ -518,7 +524,7 @@ class SwiftGenerator : public BaseGenerator {
void GenTableAccessors(const StructDef& struct_def) {
// Generate field id constants.
if (struct_def.fields.vec.size() > 0) {
code_ += "private enum {{TABLEOFFSET}}: VOffset {";
code_ += "private struct {{TABLEOFFSET}} {";
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@@ -528,10 +534,8 @@ class SwiftGenerator : public BaseGenerator {
}
code_.SetValue("OFFSET_NAME", namer_.Variable(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
code_ += "static let {{OFFSET_NAME}}: VOffset = {{OFFSET_VALUE}}";
}
code_ += "var v: Int32 { Int32(self.rawValue) }";
code_ += "var p: VOffset { self.rawValue }";
Outdent();
code_ += "}";
code_ += "";
@@ -544,13 +548,14 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("SHORT_STRUCTNAME", namer_.Type(struct_def));
code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
code_.SetValue("PROTOCOL", struct_def.fixed ? "FlatBufferStruct"
: "FlatBufferVerifiableTable");
code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
GenOSVersionChecks();
code_ +=
"{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: "
"FlatBuffer{{OBJECTTYPE}}, FlatbuffersVectorInitializable\\";
if (!struct_def.fixed) code_ += ", Verifiable\\";
"{{PROTOCOL}}, FlatbuffersVectorInitializable\\";
if (!struct_def.fixed && parser_.opts.generate_object_based_api)
code_ += ", ObjectAPIPacker\\";
code_ += " {\n";
@@ -620,7 +625,8 @@ class SwiftGenerator : public BaseGenerator {
if (should_generate_create) {
code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(";
Indent();
code_ += "_ fbb: inout FlatBufferBuilder,";
code_ += "_ fbb: inout FlatBufferBuilder\\";
if (create_func_header.empty() == false) code_ += ",";
for (auto it = create_func_header.begin(); it < create_func_header.end();
++it) {
code_ += *it + "\\";
@@ -699,7 +705,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += field.IsOptional() ? (optional_enum + "\\")
: (is_enum + ", def: {{CONSTANT}}\\");
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}) }";
const auto default_value =
IsEnum(field.value.type)
@@ -719,7 +725,7 @@ class SwiftGenerator : public BaseGenerator {
code_ +=
"{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\";
code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}) }";
create_func_header.push_back(
field_var + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
@@ -730,7 +736,7 @@ class SwiftGenerator : public BaseGenerator {
const auto create_struct =
"guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };"
" fbb.create(struct: {{FIELDVAR}}, position: "
"{{TABLEOFFSET}}.{{OFFSET}}.p) }";
"{{TABLEOFFSET}}.{{OFFSET}}) }";
code_ += type + "?" + builder_string + create_struct;
/// Optional hard coded since structs are always optional
create_func_header.push_back(field_var + ": " + type +
@@ -747,8 +753,9 @@ class SwiftGenerator : public BaseGenerator {
(field.IsRequired() ? "" : " = Offset()"));
const auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
: "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}) }"
: "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}) "
"}";
code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
const auto vectortype = field.value.type.VectorType();
@@ -852,7 +859,10 @@ class SwiftGenerator : public BaseGenerator {
break;
case BASE_TYPE_STRING: {
const auto default_string = "\"" + SwiftConstant(field) + "\"";
const auto sc = SwiftConstant(field);
std::string default_string;
flatbuffers::EscapeString(sc.c_str(), sc.length(), &default_string,
true, false);
code_.SetValue("VALUETYPE", GenType(field.value.type));
code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() +
@@ -860,7 +870,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" +
is_required +
" { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}) }";
break;
}
case BASE_TYPE_ARRAY:
@@ -894,7 +904,7 @@ class SwiftGenerator : public BaseGenerator {
code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: "
"FlatbufferVector<{{VALUETYPE}}> "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}, "
"byteSize: {{SIZE}}) }";
}
@@ -911,7 +921,7 @@ class SwiftGenerator : public BaseGenerator {
code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: "
"FlatbufferVector<{{VALUETYPE}}_Mutable> "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}, "
"byteSize: {{SIZE}}) }";
GenUnsafeBufferPointer(field);
return;
@@ -920,7 +930,8 @@ class SwiftGenerator : public BaseGenerator {
if (vectortype.base_type == BASE_TYPE_UNION) {
code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: UnionFlatbufferVector "
"{ return {{ACCESS}}.unionVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{ return {{ACCESS}}.unionVector(at: "
"{{TABLEOFFSET}}.{{OFFSET}}, "
"byteSize: {{SIZE}}) }";
code_ +=
"{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at "
@@ -954,24 +965,21 @@ class SwiftGenerator : public BaseGenerator {
"{{ACCESS_TYPE}} func {{functionName}}<T>(_ body: "
"(UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return "
"try "
"{{ACCESS}}.withUnsafePointerToSlice(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{{ACCESS}}.withUnsafePointerToSlice(at: "
"{{TABLEOFFSET}}.{{OFFSET}}, "
"body: body) }";
}
void GenerateCodingKeys(const StructDef& struct_def) {
code_ += "enum CodingKeys: String, CodingKey {";
Indent();
std::vector<std::string> GenerateCodingKeys(const StructDef& struct_def) {
std::vector<std::string> coding_keys;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto& field = **it;
if (field.deprecated) continue;
code_.SetValue("RAWVALUENAME", field.name);
code_.SetValue("FIELDVAR", namer_.Variable(field));
code_ += "case {{FIELDVAR}} = \"{{RAWVALUENAME}}\"";
coding_keys.push_back("case " + namer_.Variable(field) + " = \"" +
field.name + "\"");
}
Outdent();
code_ += "}";
return coding_keys;
}
void GenerateEncoderUnionBody(const FieldDef& field) {
@@ -1093,14 +1101,31 @@ class SwiftGenerator : public BaseGenerator {
GenOSVersionChecks();
code_ += "extension {{STRUCTNAME}}: Encodable {";
Indent();
code_ += "";
if (struct_def.fields.vec.empty() == false) GenerateCodingKeys(struct_def);
auto coding_keys = GenerateCodingKeys(struct_def);
if (coding_keys.empty() == false) {
code_ += "enum CodingKeys: String, CodingKey {";
Indent();
for (auto it = coding_keys.begin(); it != coding_keys.end(); ++it) {
const auto& field = *it;
code_ += field;
}
Outdent();
code_ += "}";
code_ += "";
}
code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
Indent();
if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
Outdent();
if (coding_keys.empty() == false) {
Indent();
GenerateEncoderBody(struct_def);
Outdent();
}
code_ += "}";
Outdent();
code_ += "}";
code_ += "";
@@ -1130,7 +1155,7 @@ class SwiftGenerator : public BaseGenerator {
}
code_ +=
"try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
"try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}, fieldName: "
"\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: "
"{{VALUETYPE}}.self)";
}
@@ -1150,8 +1175,9 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def));
code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
code_ +=
"try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
"unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
"try _v.{{FUNCTION_NAME}}(unionKey: "
"{{TABLEOFFSET}}.{{OFFSET}}Type, "
"unionField: {{TABLEOFFSET}}.{{OFFSET}}, unionKeyName: "
"\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: "
"{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
Indent();
@@ -1626,15 +1652,23 @@ class SwiftGenerator : public BaseGenerator {
buffer_constructor.push_back(field_var + " = _t." + field_field);
if (field.IsRequired()) {
std::string default_value =
field.IsDefault() ? SwiftConstant(field) : "";
base_constructor.push_back(field_var + " = \"" + default_value +
"\"");
std::string default_value;
if (field.IsDefault()) {
const auto sc = SwiftConstant(field);
flatbuffers::EscapeString(sc.c_str(), sc.length(), &default_value,
true, false);
} else {
default_value = "\"\"";
}
base_constructor.push_back(field_var + " = " + default_value);
break;
}
if (field.IsDefault() && !field.IsRequired()) {
std::string value = field.IsDefault() ? SwiftConstant(field) : "nil";
base_constructor.push_back(field_var + " = \"" + value + "\"");
const auto sc = SwiftConstant(field);
std::string value;
flatbuffers::EscapeString(sc.c_str(), sc.length(), &value,
true, false);
base_constructor.push_back(field_var + " = " + value);
}
break;
}
@@ -1893,7 +1927,7 @@ class SwiftGenerator : public BaseGenerator {
}
std::string GenOffset() {
return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}); ";
}
std::string GenReaderMainBody(const std::string& optional = "") {
+169 -53
View File
@@ -324,9 +324,10 @@ class TsGenerator : public BaseGenerator {
export_counter++;
}
if (export_counter > 0)
if (export_counter > 0) {
parser_.opts.file_saver->SaveFile(it.second.filepath.c_str(), code,
false);
}
}
}
@@ -521,7 +522,20 @@ class TsGenerator : public BaseGenerator {
case BASE_TYPE_BOOL:
return value.constant == "0" ? "false" : "true";
case BASE_TYPE_STRING:
case BASE_TYPE_STRING: {
// NOTE: Strings without a default value are parsed as "0" by
// the parser, so therefore we have to treat "0" as a null-signifying
// value.
if (value.constant == "0" || value.constant == "null") {
return "null";
} else {
std::string escaped;
flatbuffers::EscapeString(value.constant.c_str(),
value.constant.length(), &escaped,
true, false);
return escaped;
}
}
case BASE_TYPE_UNION:
case BASE_TYPE_STRUCT: {
return null_keyword_;
@@ -647,7 +661,8 @@ class TsGenerator : public BaseGenerator {
}
void GenStructArgs(import_set& imports, const StructDef& struct_def,
std::string* arguments, const std::string& nameprefix) {
const Definition& owner, std::string* arguments,
const std::string& nameprefix) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto& field = **it;
@@ -655,11 +670,11 @@ class TsGenerator : public BaseGenerator {
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
GenStructArgs(imports, *field.value.type.struct_def, arguments,
GenStructArgs(imports, *field.value.type.struct_def, owner, arguments,
nameprefix + field.name + "_");
} else {
*arguments += ", " + nameprefix + field.name + ": " +
GenTypeName(imports, field, field.value.type, true,
GenTypeName(imports, owner, field.value.type, true,
field.IsOptional());
}
}
@@ -921,6 +936,48 @@ class TsGenerator : public BaseGenerator {
return symbols_expression;
}
std::vector<std::string> PathComponents(const std::string& path) const {
std::vector<std::string> components;
size_t start = 0;
while (start < path.size()) {
auto end = path.find(kPathSeparator, start);
if (end == std::string::npos) end = path.size();
if (end > start) {
components.emplace_back(path.substr(start, end - start));
}
if (end == path.size()) break;
start = end + 1;
}
return components;
}
std::string RelativeDirectory(const std::vector<std::string>& from,
const std::vector<std::string>& to) const {
size_t common = 0;
while (common < from.size() && common < to.size() &&
from[common] == to[common]) {
++common;
}
std::string rel;
const size_t ups = from.size() - common;
if (ups == 0) {
rel = ".";
} else {
for (size_t i = 0; i < ups; ++i) {
if (!rel.empty()) rel += kPathSeparator;
rel += "..";
}
}
for (size_t i = common; i < to.size(); ++i) {
if (!rel.empty()) rel += kPathSeparator;
rel += to[i];
}
return rel;
}
template <typename DefinitionT>
ImportDefinition AddImport(import_set& imports, const Definition& dependent,
const DefinitionT& dependency) {
@@ -948,26 +1005,32 @@ class TsGenerator : public BaseGenerator {
const std::string symbols_expression = GenSymbolExpression(
dependency, has_name_clash, import_name, name, object_name);
std::string bare_file_path;
std::string rel_file_path;
if (dependent.defined_namespace) {
const auto& dep_comps = dependent.defined_namespace->components;
for (size_t i = 0; i < dep_comps.size(); i++) {
rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
}
if (dep_comps.size() == 0) {
rel_file_path += ".";
}
} else {
rel_file_path += "..";
}
const Namespace* dependent_ns = dependent.defined_namespace
? dependent.defined_namespace
: parser_.empty_namespace_;
const Namespace* dependency_ns = dependency.defined_namespace
? dependency.defined_namespace
: parser_.empty_namespace_;
bare_file_path +=
kPathSeparator +
namer_.Directories(dependency.defined_namespace->components,
SkipDir::OutputPath) +
const std::string dependent_dirs =
namer_.Directories(*dependent_ns, SkipDir::OutputPath);
const std::string dependency_dirs =
namer_.Directories(*dependency_ns, SkipDir::OutputPath);
const auto dependent_components = PathComponents(dependent_dirs);
const auto dependency_components = PathComponents(dependency_dirs);
std::string rel_dir =
RelativeDirectory(dependent_components, dependency_components);
if (rel_dir.empty()) rel_dir = ".";
if (!rel_dir.empty()) rel_dir += kPathSeparator;
std::string rel_file_path =
rel_dir + namer_.File(dependency, SkipFile::SuffixAndExtension);
std::string bare_file_path =
kPathSeparator + dependency_dirs +
namer_.File(dependency, SkipFile::SuffixAndExtension);
rel_file_path += bare_file_path;
ImportDefinition import;
import.name = name;
@@ -1172,9 +1235,10 @@ class TsGenerator : public BaseGenerator {
std::string GenNullCheckConditional(const std::string& nullCheckVar,
const std::string& trueVal,
const std::string& falseVal) {
const std::string& falseVal = "") {
std::string false_val = falseVal.empty() ? null_keyword_ : falseVal;
return "(" + nullCheckVar + " !== " + null_keyword_ + " ? " + trueVal +
" : " + falseVal + ")";
" : " + false_val + ")";
}
std::string GenStructMemberValueTS(const StructDef& struct_def,
@@ -1283,10 +1347,9 @@ class TsGenerator : public BaseGenerator {
// Emit a scalar field
const auto is_string = IsString(field.value.type);
if (IsScalar(field.value.type.base_type) || is_string) {
const auto has_null_default = is_string || HasNullDefault(field);
field_type += GenTypeName(imports, field, field.value.type, false,
has_null_default);
field_type +=
GenTypeName(imports, field, field.value.type, false,
!HasDefaultValue(field) || HasNullDefault(field));
field_val = "this." + namer_.Method(field) + "()";
if (field.value.type.base_type != BASE_TYPE_STRING) {
@@ -1632,11 +1695,12 @@ class TsGenerator : public BaseGenerator {
GenDocComment(struct_def.doc_comment, code_ptr);
code += "export class ";
code += object_name;
if (parser.opts.generate_object_based_api)
if (parser.opts.generate_object_based_api) {
code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
"> {\n";
else
} else {
code += " {\n";
}
code += " bb: flatbuffers.ByteBuffer|" + null_keyword_ + " = " +
null_keyword_ + ";\n";
code += " bb_pos = 0;\n";
@@ -1679,21 +1743,22 @@ class TsGenerator : public BaseGenerator {
offset_prefix = " const offset = " + GenBBAccess() +
".__offset(this.bb_pos, " +
NumToString(field.value.offset) + ");\n";
offset_prefix += " return offset ? ";
offset_prefix += " return ";
}
// Emit a scalar field
const auto is_string = IsString(field.value.type);
if (IsScalar(field.value.type.base_type) || is_string) {
const auto has_null_default = is_string || HasNullDefault(field);
const auto has_null_default =
!field.IsRequired() && !HasDefaultValue(field);
GenDocComment(field.doc_comment, code_ptr);
std::string prefix = namer_.Method(field) + "(";
if (is_string) {
code += prefix + "):string|" + null_keyword_ + "\n";
code += prefix + "):" + (has_null_default ? "string|" + null_keyword_ : "string") + "\n";
code +=
prefix + "optionalEncoding:flatbuffers.Encoding" + "):" +
GenTypeName(imports, struct_def, field.value.type, false, true) +
GenTypeName(imports, struct_def, field.value.type, false, has_null_default) +
"\n";
code += prefix + "optionalEncoding?:any";
} else {
@@ -1722,9 +1787,16 @@ class TsGenerator : public BaseGenerator {
if (is_string) {
index += ", optionalEncoding";
}
code +=
offset_prefix + GenGetter(field.value.type, "(" + index + ")");
if (field.value.type.base_type != BASE_TYPE_ARRAY) {
if (field.IsRequired()) {
code +=
offset_prefix + GenGetter(field.value.type, "(" + index + ")");
;
} else {
code += offset_prefix + "offset ? " +
GenGetter(field.value.type, "(" + index + ")");
}
if (field.value.type.base_type != BASE_TYPE_ARRAY &&
!field.IsRequired()) {
code += " : " + GenDefaultValue(field, imports);
}
code += ";\n";
@@ -1749,8 +1821,8 @@ class TsGenerator : public BaseGenerator {
code +=
MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n";
} else {
code += offset_prefix + "(obj || " + GenerateNewExpression(type) +
").__init(";
code += offset_prefix + "offset ? (obj || " +
GenerateNewExpression(type) + ").__init(";
code += field.value.type.struct_def->fixed
? "this.bb_pos + offset"
: GenBBAccess() + ".__indirect(this.bb_pos + offset)";
@@ -1908,7 +1980,7 @@ class TsGenerator : public BaseGenerator {
code += "):" + vectortypename + "|" + null_keyword_ + " {\n";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
code += offset_prefix + "(obj || " +
code += offset_prefix + "offset ? (obj || " +
GenerateNewExpression(vectortypename);
code += ").__init(";
code += vectortype.struct_def->fixed
@@ -1921,7 +1993,8 @@ class TsGenerator : public BaseGenerator {
} else if (IsString(vectortype)) {
index += ", optionalEncoding";
}
code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
code += offset_prefix + "offset ? " +
GenGetter(vectortype, "(" + index + ")");
}
code += " : ";
if (field.value.type.element == BASE_TYPE_BOOL) {
@@ -1953,7 +2026,7 @@ class TsGenerator : public BaseGenerator {
" "
"{\n";
code += offset_prefix +
code += offset_prefix + "offset ? " +
GenGetter(field.value.type, "(obj, this.bb_pos + offset)") +
" : " + null_keyword_ + ";\n";
break;
@@ -2006,7 +2079,7 @@ class TsGenerator : public BaseGenerator {
// Emit a length helper
GenDocComment(code_ptr);
code += namer_.Method(field, "Length");
code += "():number {\n" + offset_prefix;
code += "():number {\n" + offset_prefix + "offset ? ";
code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
@@ -2017,15 +2090,30 @@ class TsGenerator : public BaseGenerator {
GenDocComment(code_ptr);
code += namer_.Method(field, "Array");
code += "():" + GenType(vectorType) + "Array|" + null_keyword_ +
" {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
".bytes().buffer, " + GenBBAccess() +
".bytes().byteOffset + " + GenBBAccess() +
".__vector(this.bb_pos + offset), " + GenBBAccess() +
".__vector_len(this.bb_pos + offset)) : " + null_keyword_ +
";\n}\n\n";
std::string return_type =
(field.IsRequired() || HasDefaultValue(field))
? "Array"
: ("Array|" + null_keyword_);
if (field.IsRequired()) {
code += "():" + GenType(vectorType) + return_type + " {\n" +
offset_prefix + "new " + GenType(vectorType) + "Array(" +
GenBBAccess() + ".bytes().buffer, " + GenBBAccess() +
".bytes().byteOffset + " + GenBBAccess() +
".__vector(this.bb_pos + offset), " + GenBBAccess() +
".__vector_len(this.bb_pos + offset));\n}\n\n";
} else {
std::string value = HasDefaultValue(field)
? "new " + GenType(vectorType) + "Array()"
: "null";
code += "():" + GenType(vectorType) + return_type + " {\n" +
offset_prefix + "offset ? new " + GenType(vectorType) +
"Array(" + GenBBAccess() + ".bytes().buffer, " +
GenBBAccess() + ".bytes().byteOffset + " + GenBBAccess() +
".__vector(this.bb_pos + offset), " + GenBBAccess() +
".__vector_len(this.bb_pos + offset)) : " + value +
";\n}\n\n";
}
}
}
}
@@ -2054,7 +2142,7 @@ class TsGenerator : public BaseGenerator {
// Emit a factory constructor
if (struct_def.fixed) {
std::string arguments;
GenStructArgs(imports, struct_def, &arguments, "");
GenStructArgs(imports, struct_def, struct_def, &arguments, "");
GenDocComment(code_ptr);
code += "static create" + GetPrefixedName(struct_def) +
@@ -2256,6 +2344,34 @@ class TsGenerator : public BaseGenerator {
return field.IsOptional() && field.value.constant == "null";
}
static bool HasDefaultValue(const FieldDef& field) {
switch (field.value.type.base_type) {
// These types can't have defaults
case BASE_TYPE_UNION:
case BASE_TYPE_STRUCT: {
return false;
}
// Arrays always have a default (empty array)
case BASE_TYPE_ARRAY:
return true;
// The only supported default for vectors is []
case BASE_TYPE_VECTOR:
return field.value.constant == "[]";
// Even strings are presumed to be null-default if the default value is
// "0", this is intended behavior.
case BASE_TYPE_STRING: {
return field.value.constant != "0" && field.value.constant != "null";
}
default: {
return field.value.constant != "null";
}
}
}
std::string GetArgType(import_set& imports, const Definition& owner,
const FieldDef& field, bool allowNull) {
return GenTypeName(imports, owner, field.value.type, true,
+15 -53
View File
@@ -1286,55 +1286,6 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
"'native_inline' can only be defined on structs, vector of structs or "
"vector of tables");
// `bigfoot_ref` is Bigfoot's single-purpose replacement for the old,
// general-purpose `native_type_template`/`native_type_template_arg` pair:
// a field typed as a `bigfoot_ref_wrapper`-tagged struct (HardReference or
// SoftReference) and annotated `bigfoot_ref: "::Bigfoot::AssetX"` gets its
// native type instantiated as `<wrapper><::Bigfoot::AssetX>`, plus (unlike
// the old mechanism) a forward declaration of AssetX and inline Pack/UnPack
// definitions are emitted directly into the generated header - see
// GenerateBigfootRefDecls in idl_gen_cpp.cpp.
auto bigfoot_ref = field->attributes.Lookup("bigfoot_ref");
if (bigfoot_ref) {
if (!IsStruct(field->value.type) && !IsVectorOfStruct(field->value.type))
return Error(
"'bigfoot_ref' can only be defined on struct-typed fields or "
"vectors of structs");
const auto* target_struct = field->value.type.struct_def;
const auto* wrapper = target_struct->attributes.Lookup("bigfoot_ref_wrapper");
if (!wrapper)
return Error(
"'bigfoot_ref' requires the field's type ('" + target_struct->name +
"') to declare a 'bigfoot_ref_wrapper' attribute");
if (field->attributes.Lookup("native_type"))
return Error(
"'bigfoot_ref' cannot be combined with an explicit 'native_type' "
"on the same field");
const auto b = bigfoot_ref->constant.find_first_not_of(" \t");
const auto e = bigfoot_ref->constant.find_last_not_of(" \t");
const std::string asset_type =
b == std::string::npos ? "" : bigfoot_ref->constant.substr(b, e - b + 1);
if (asset_type.empty())
return Error("'bigfoot_ref' cannot be empty");
auto native_type_val = new Value();
native_type_val->type = bigfoot_ref->type;
native_type_val->constant = wrapper->constant + "<" + asset_type + ">";
field->attributes.Add("native_type", native_type_val);
if (!field->attributes.Lookup("native_type_pack_name")) {
const auto last_colon = asset_type.find_last_of(':');
const std::string asset_short_name =
last_colon == std::string::npos ? asset_type
: asset_type.substr(last_colon + 1);
auto pack_name_val = new Value();
pack_name_val->type = bigfoot_ref->type;
pack_name_val->constant = target_struct->name + asset_short_name;
field->attributes.Add("native_type_pack_name", pack_name_val);
}
}
auto nested = field->attributes.Lookup("nested_flatbuffer");
if (nested) {
if (nested->type.base_type != BASE_TYPE_STRING)
@@ -2858,7 +2809,8 @@ bool Parser::SupportsOptionalScalars() const {
bool Parser::SupportsDefaultVectorsAndStrings() const {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim |
IDLOptions::kCpp | IDLOptions::kBinary | IDLOptions::kJson;
IDLOptions::kCpp | IDLOptions::kBinary | IDLOptions::kJson |
IDLOptions::kTs;
return !(opts.lang_to_generate & ~supported_langs);
}
@@ -3220,8 +3172,10 @@ CheckedError Parser::ParseProtoFields(StructDef* struct_def, bool isextend,
return Error("Protobuf has non positive number in reserved ids");
if (range) {
for (voffset_t id = from + 1; id <= attribute; id++)
struct_def->reserved_ids.push_back(id);
for (uint32_t id = static_cast<uint32_t>(from) + 1;
id <= static_cast<uint32_t>(attribute); id++) {
struct_def->reserved_ids.push_back(static_cast<voffset_t>(id));
}
range = false;
} else {
@@ -4178,7 +4132,15 @@ bool StructDef::Deserialize(Parser& parser, const reflection::Object* object) {
sortbysize = attributes.Lookup("original_order") == nullptr && !fixed;
const auto& of = *(object->fields());
auto indexes = std::vector<uoffset_t>(of.size());
for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = i;
for (uoffset_t i = 0; i < of.size(); i++) {
uint16_t field_id = of.Get(i)->id();
if (field_id >= of.size()) {
parser.error_ = "Field ID " + std::to_string(field_id) +
" exceeds field count " + std::to_string(of.size());
return false;
}
indexes[field_id] = i;
}
size_t tmp_struct_size = 0;
for (size_t i = 0; i < indexes.size(); i++) {
auto field = of.Get(indexes[i]);
+5 -2
View File
@@ -389,7 +389,7 @@ void ForAllFields(const reflection::Object* object, bool reverse,
for (size_t i = 0; i < field_to_id_map.size(); ++i) {
func(object->fields()->Get(
field_to_id_map[reverse ? field_to_id_map.size() - i + 1 : i]));
field_to_id_map[reverse ? field_to_id_map.size() - (i + 1) : i]));
}
}
@@ -641,7 +641,10 @@ const uint8_t* AddFlatBuffer(std::vector<uint8_t>& flatbuf,
const uint8_t* newbuf, size_t newlen) {
// Align to sizeof(uoffset_t) past sizeof(largest_scalar_t) since we're
// going to chop off the root offset.
if (!newbuf || newlen < sizeof(uoffset_t)) return nullptr;
FLATBUFFERS_ASSERT(newlen >= sizeof(uoffset_t));
auto root = ReadScalar<uoffset_t>(newbuf);
if (root < sizeof(uoffset_t) || root >= newlen) return nullptr;
while ((flatbuf.size() & (sizeof(uoffset_t) - 1)) ||
!(flatbuf.size() & (sizeof(largest_scalar_t) - 1))) {
flatbuf.push_back(0);
@@ -649,7 +652,7 @@ const uint8_t* AddFlatBuffer(std::vector<uint8_t>& flatbuf,
auto insertion_point = static_cast<uoffset_t>(flatbuf.size());
// Insert the entire FlatBuffer minus the root pointer.
flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen);
auto root_offset = ReadScalar<uoffset_t>(newbuf) - sizeof(uoffset_t);
auto root_offset = root - sizeof(uoffset_t);
return flatbuf.data() + insertion_point + root_offset;
}
+1 -1
View File
@@ -28,7 +28,7 @@ public let FileIdLength = 4
/// Protocol that All Scalars should conform to
///
/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
public protocol Scalar: Equatable, BitwiseCopyable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}
+48 -11
View File
@@ -20,22 +20,56 @@ import Foundation
/// it allows users to write and read data directly from memory thus the use of its
/// functions should be used
@frozen
public struct ByteBuffer {
public struct ByteBuffer: @unchecked Sendable {
/// Storage is a container that would hold the memory pointer to solve the issue of
/// deallocating the memory that was held by (memory: UnsafeMutableRawPointer)
@usableFromInline
final class Storage {
@usableFromInline
enum Blob {
@frozen enum Blob: ~Copyable {
#if !os(WASI)
case data(Data)
case bytes(ContiguousBytes)
case bytes(any ContiguousBytes)
#endif
case byteBuffer(_InternalByteBuffer)
case array([UInt8])
case pointer(UnsafeMutableRawPointer)
init(_ other: borrowing Blob) {
switch other {
#if !os(WASI)
case .data(let data):
self = .data(data)
case .bytes(let contiguousBytes):
self = .bytes(contiguousBytes)
#endif
case .byteBuffer(let internalByteBuffer):
self = .byteBuffer(internalByteBuffer)
case .array(let array):
self = .array(array)
case .pointer(let unsafeMutableRawPointer):
self = .pointer(unsafeMutableRawPointer)
}
}
var description: String {
switch self {
#if !os(WASI)
case .data(let data):
"data: \(data)"
case .bytes(let contiguousBytes):
"bytes: \(contiguousBytes)"
#endif
case .byteBuffer(let internalByteBuffer):
"byteBuffer: \(internalByteBuffer)"
case .array(let array):
"array: \(array)"
case .pointer(let unsafeMutableRawPointer):
"pointer: \(unsafeMutableRawPointer)"
}
}
}
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -44,7 +78,7 @@ public struct ByteBuffer {
private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline
var retainedBlob: Blob
let retainedBlob: Blob
@usableFromInline
init(count: Int) {
@@ -57,9 +91,9 @@ public struct ByteBuffer {
}
@usableFromInline
init(blob: Blob, capacity count: Int) {
init(blob: borrowing Blob, capacity count: Int) {
capacity = count
retainedBlob = blob
retainedBlob = .init(blob)
isOwned = false
}
@@ -150,6 +184,7 @@ public struct ByteBuffer {
@discardableResult
@inline(__always)
@inlinable
func readWithUnsafeRawPointer<T>(
position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
@@ -278,7 +313,7 @@ public struct ByteBuffer {
/// - removeBytes: Removes a number of bytes from the current size
@inline(__always)
init(
blob: Storage.Blob,
blob: borrowing Storage.Blob,
count: Int,
removing removeBytes: Int)
{
@@ -318,7 +353,8 @@ public struct ByteBuffer {
/// - def: Type of the object
/// - position: the index of the object in the buffer
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
@inlinable
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1)
.pointee
@@ -412,7 +448,7 @@ public struct ByteBuffer {
/// - Parameter removeBytes: the amount of bytes to remove from the current Size
@inline(__always)
public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
assert(removeBytes > 0, "Can NOT remove negative bytes")
assert(removeBytes >= 0, "Can NOT remove negative bytes")
assert(
removeBytes < capacity,
"Can NOT remove more bytes than the ones allocated")
@@ -464,8 +500,9 @@ public struct ByteBuffer {
extension ByteBuffer: CustomDebugStringConvertible {
public var debugDescription: String {
"""
buffer located at: \(_storage.retainedBlob),
let blobDescription = _storage.retainedBlob.description
return """
buffer located at: \(blobDescription),
with capacity of \(capacity),
{ writtenSize: \(_readerIndex), readerSize: \(reader),
size: \(size) }
+1 -1
View File
@@ -23,7 +23,7 @@ import Common
/// Enum is a protocol that all flatbuffers enums should conform to
/// Since it allows us to get the actual `ByteSize` and `Value` from
/// a swift enum.
public protocol Enum {
public protocol Enum: Sendable {
/// associatedtype that the type of the enum should conform to
associatedtype T: Scalar & Verifiable
/// Size of the current associatedtype in the enum
@@ -45,9 +45,10 @@ public struct FlatBufferBuilder {
/// Dictonary that stores a map of all the strings that were written to the buffer
private var stringOffsetMap: [String: Offset] = [:]
/// A check to see if finish(::) was ever called to retreive data object
private var finished = false
private(set) var finished = false
/// A check to see if the buffer should serialize Default values
private var serializeDefaults: Bool
@usableFromInline
let serializeDefaults: Bool
/// Current alignment for the buffer
var _minAlignment: Int = 0 {
@@ -488,7 +489,7 @@ public struct FlatBufferBuilder {
///
/// - Parameter bytes: bytes to be written into the buffer
/// - Returns: ``Offset`` of the vector
mutating public func createVector(bytes: ContiguousBytes) -> Offset {
mutating public func createVector(bytes: any ContiguousBytes) -> Offset {
bytes.withUnsafeBytes {
startVector($0.count, elementSize: MemoryLayout<UInt8>.size)
_bb.push(bytes: $0)
@@ -756,6 +757,7 @@ public struct FlatBufferBuilder {
/// - offset: ``Offset`` of another object to be written
/// - position: The predefined position of the object
@inline(__always)
@inlinable
mutating public func add(offset: Offset, at position: VOffset) {
if offset.isEmpty { return }
add(element: refer(to: offset.o), def: 0, at: position)
@@ -794,6 +796,7 @@ public struct FlatBufferBuilder {
/// - def: Default value for that element
/// - position: The predefined position of the element
@inline(__always)
@inlinable
mutating public func add<T: Scalar>(
element: T,
def: T,
@@ -813,6 +816,7 @@ public struct FlatBufferBuilder {
/// - element: Optional element of type scalar
/// - position: The predefined position of the element
@inline(__always)
@inlinable
mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
guard let element = element else { return }
track(offset: push(element: element), at: position)
@@ -825,6 +829,7 @@ public struct FlatBufferBuilder {
/// - Parameter element: Element to insert
/// - returns: position of the Element
@inline(__always)
@inlinable
@discardableResult
mutating public func push<T: Scalar>(element: T) -> UOffset {
let size = MemoryLayout<T>.size
@@ -836,7 +841,8 @@ public struct FlatBufferBuilder {
}
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
@inlinable
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_bb.read(def: def, position: position)
}
}
@@ -18,7 +18,9 @@ import Foundation
/// NativeStruct is a protocol that indicates if the struct is a native `swift` struct
/// since now we will be serializing native structs into the buffer.
public protocol NativeStruct {}
public protocol NativeStruct: BitwiseCopyable {}
public protocol FlatBufferVerifiableNativeStruct: NativeStruct, Verifiable {}
/// FlatbuffersInitializable is a protocol that allows any object to be
/// Initialized from a ByteBuffer
@@ -35,6 +37,8 @@ public protocol FlatBufferTable: FlatbuffersInitializable,
var __buffer: ByteBuffer! { get }
}
public protocol FlatBufferVerifiableTable: FlatBufferTable, Verifiable {}
/// FlatbufferStruct structures all the Flatbuffers structs
public protocol FlatBufferStruct: FlatbuffersInitializable,
FlatbuffersVectorInitializable
+63 -34
View File
@@ -16,50 +16,52 @@
import Foundation
/// FlatBufferGRPCMessage protocol that should allow us to invoke
/// initializers directly from the GRPC generated code
public protocol FlatBufferGRPCMessage {
/// Size of readable bytes in the buffer
var size: Int { get }
init(byteBuffer: ByteBuffer)
@discardableResult
@inline(__always)
func withUnsafeReadableBytes<T>(
_ body: (UnsafeRawBufferPointer) throws
-> T) rethrows -> T
enum FlatbuffersGRPCError: Error {
case finishedNotCalledOnBuilder
}
/// Message is a wrapper around Buffers to to able to send Flatbuffers `Buffers` through the
/// GRPC library
public struct Message<T: FlatBufferTable>: FlatBufferGRPCMessage {
internal var buffer: ByteBuffer
public protocol GRPCVerifiableMessage<Message> {
associatedtype Message
/// Returns the an object of type T that would be read from the buffer
public var object: T {
T.init(
buffer,
o: Int32(buffer.read(def: UOffset.self, position: buffer.reader)) &+
Int32(buffer.reader))
}
init(pointer: UnsafeRawBufferPointer)
init(byteBuffer: ByteBuffer)
func decode() throws -> Message
func withUnsafeReadableBytes<Data>(
_ body: (UnsafeRawBufferPointer) throws
-> Data) rethrows -> Data
}
public struct GRPCMessage<
Table: FlatBufferVerifiableTable
>: Sendable, GRPCVerifiableMessage {
public typealias Message = Table
private let buffer: ByteBuffer
public var size: Int { Int(buffer.size) }
/// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over
/// GRPC
/// - Parameter byteBuffer: Flatbuffer ByteBuffer object
public init(pointer: UnsafeRawBufferPointer) {
buffer = ByteBuffer(
copyingMemoryBound: pointer.baseAddress!,
capacity: pointer.count)
}
public init(builder: inout FlatBufferBuilder) throws {
guard builder.finished else {
throw FlatbuffersGRPCError.finishedNotCalledOnBuilder
}
buffer = builder.sizedBuffer
}
public init(byteBuffer: ByteBuffer) {
buffer = byteBuffer
}
/// Initializes the message by copying the buffer to the message to be sent.
/// from the builder
/// - Parameter builder: FlatbufferBuilder that has the bytes created in
/// - Note: Use `builder.finish(offset)` before passing the builder without prefixing anything to it
public init(builder: inout FlatBufferBuilder) {
buffer = builder.sizedBuffer
builder.clear()
public func decode() throws -> Table {
var buf = buffer
return try getCheckedRoot(byteBuffer: &buf)
}
@discardableResult
@@ -73,3 +75,30 @@ public struct Message<T: FlatBufferTable>: FlatBufferGRPCMessage {
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public struct FlatBuffersMessageSerializer<
Message: GRPCVerifiableMessage
>: Sendable {
public init() {}
public func serialize<Data>(
message: Message,
_ completion: (UnsafeRawBufferPointer) throws -> Data) throws -> Data
{
return try message.withUnsafeReadableBytes {
try completion($0)
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public struct FlatBuffersMessageDeserializer<
Message: GRPCVerifiableMessage
>: Sendable {
public init() {}
public func deserialize(pointer: UnsafeRawBufferPointer) throws -> Message {
Message.init(pointer: pointer)
}
}
+38 -8
View File
@@ -16,6 +16,30 @@
import Foundation
@inline(__always)
private func verifySizePrefix(
byteBuffer: inout ByteBuffer,
requireExactSize: Bool,
options: VerifierOptions) throws
{
let verifier = try Verifier(buffer: &byteBuffer, options: options)
let prefixPosition = byteBuffer.reader
let prefix: UOffset = try verifier.getValue(at: prefixPosition)
let availableSize = byteBuffer.size &- UOffset(MemoryLayout<UOffset>.size)
if requireExactSize {
guard prefix == availableSize else {
throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
}
} else if prefix > availableSize {
throw FlatbuffersErrors.outOfBounds(
position: UInt(prefixPosition)
&+ UInt(MemoryLayout<UOffset>.size)
&+ UInt(prefix),
end: byteBuffer.capacity)
}
}
/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
/// - Parameters:
@@ -31,6 +55,10 @@ public func getPrefixedSizeCheckedRoot<T: FlatBufferTable & Verifiable>(
fileId: String? = nil,
options: VerifierOptions = .init()) throws -> T
{
try verifySizePrefix(
byteBuffer: &byteBuffer,
requireExactSize: false,
options: options)
byteBuffer.skipPrefix()
return try getCheckedRoot(
byteBuffer: &byteBuffer,
@@ -53,10 +81,11 @@ public func getCheckedPrefixedSizeRoot<T: FlatBufferTable & Verifiable>(
fileId: String? = nil,
options: VerifierOptions = .init()) throws -> T
{
let prefix = byteBuffer.skipPrefix()
if prefix != byteBuffer.size {
throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
}
try verifySizePrefix(
byteBuffer: &byteBuffer,
requireExactSize: true,
options: options)
byteBuffer.skipPrefix()
return try getCheckedRoot(
byteBuffer: &byteBuffer,
fileId: fileId,
@@ -95,14 +124,15 @@ public func getCheckedRoot<T: FlatBufferTable & Verifiable>(
options: VerifierOptions = .init()) throws -> T
{
var verifier = try Verifier(buffer: &byteBuffer, options: options)
let rootPosition = byteBuffer.reader
if let fileId = fileId {
try verifier.verify(id: fileId)
try verifier.verify(id: fileId, at: rootPosition)
}
try ForwardOffset<T>.verify(&verifier, at: 0, of: T.self)
try ForwardOffset<T>.verify(&verifier, at: rootPosition, of: T.self)
return T.init(
byteBuffer,
o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader))
&+ Int32(byteBuffer.reader))
o: Int32(byteBuffer.read(def: UOffset.self, position: rootPosition))
&+ Int32(rootPosition))
}
/// Returns a `NON-Checked` flatbuffers object
+7 -7
View File
@@ -49,7 +49,7 @@ public struct Table {
/// the vtable
/// - Parameter o: current offset
/// - Returns: offset of field within buffer
public func offset(_ o: Int32) -> Int32 {
public func offset(_ o: VOffset) -> Int32 {
let vtable = position &- bb.read(def: Int32.self, position: Int(position))
return o
< bb
@@ -57,7 +57,7 @@ public struct Table {
? Int32(
bb.read(
def: Int16.self,
position: Int(vtable &+ o))) : 0
position: Int(vtable &+ Int32(o)))) : 0
}
/// Gets the indirect offset of the current stored object
@@ -82,7 +82,7 @@ public struct Table {
/// - Parameters:
/// - type: Type of Element that needs to be read from the buffer
/// - o: Offset of the Element
public func readBuffer<T>(of type: T.Type, at o: Int32) -> T {
public func readBuffer<T: BitwiseCopyable>(of type: T.Type, at o: Int32) -> T {
bb.read(def: T.self, position: Int(o &+ position))
}
@@ -106,13 +106,13 @@ public struct Table {
/// This should only be used by `Scalars`
/// - Parameter off: Readable offset
/// - Returns: Returns a vector of type [T]
public func getVector<T>(at off: Int32) -> [T]? {
public func getVector<T>(at off: VOffset) -> [T]? {
let o = offset(off)
guard o != 0 else { return nil }
return bb.readSlice(index: Int(vector(at: o)), count: Int(vector(count: o)))
}
public func vector<T>(at off: Int32, byteSize: Int) -> FlatbufferVector<T> {
public func vector<T>(at off: VOffset, byteSize: Int) -> FlatbufferVector<T> {
let off = offset(off)
return FlatbufferVector(
bb: bb,
@@ -122,7 +122,7 @@ public struct Table {
}
public func unionVector(
at off: Int32,
at off: VOffset,
byteSize: Int) -> UnionFlatbufferVector
{
let off = offset(off)
@@ -146,7 +146,7 @@ public struct Table {
/// - Returns: Returns a pointer to the underlying data
@inline(__always)
public func withUnsafePointerToSlice<T>(
at off: Int32,
at off: VOffset,
body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T?
{
let o = offset(off)
@@ -115,7 +115,7 @@ public struct TableVerifier {
unionKeyName: String,
fieldName: String,
required: Bool,
completion: @escaping (inout Verifier, T, Int) throws -> Void) throws
completion: (inout Verifier, T, Int) throws -> Void) throws
where T: UnionEnum
{
let keyPos = try dereference(key)
@@ -68,7 +68,7 @@ public struct FlatbufferVector<
}
extension FlatbufferVector: Encodable where Element: Encodable {
public func encode(to encoder: Encoder) throws {
public func encode(to encoder: any Encoder) throws {
var container = encoder.unkeyedContainer()
for element in self {
try container.encode(element)
@@ -49,8 +49,8 @@ public struct UnionFlatbufferVector {
public subscript(
position: Int,
Type: FlatbuffersVectorInitializable
.Type) -> FlatbuffersVectorInitializable
Type: any FlatbuffersVectorInitializable
.Type) -> any FlatbuffersVectorInitializable
{
guard position < count else {
fatalError(
+8 -1
View File
@@ -56,8 +56,15 @@ extension Verifiable {
let len: UOffset = try verifier.getValue(at: position)
let intLen = Int(len)
let start = Int(clamping: (position &+ MemoryLayout<Int32>.size).magnitude)
let byteCount = intLen.multipliedReportingOverflow(
by: MemoryLayout<T>.size)
guard !byteCount.overflow else {
throw FlatbuffersErrors.outOfBounds(
position: UInt.max,
end: verifier.capacity)
}
try verifier.isAligned(position: start, type: type.self)
try verifier.rangeInBuffer(position: start, size: intLen)
try verifier.rangeInBuffer(position: start, size: byteCount.partialValue)
return (start, intLen)
}
}
+8 -4
View File
@@ -163,7 +163,7 @@ public struct Verifier {
/// - Parameter position: Current position to be read
/// - Throws: `inBuffer` errors
/// - Returns: a value of type `T` usually a `VTable` or a table offset
internal func getValue<T>(at position: Int) throws -> T {
internal func getValue<T: BitwiseCopyable>(at position: Int) throws -> T {
try inBuffer(position: position, of: T.self)
return _buffer.read(def: T.self, position: position)
}
@@ -215,12 +215,16 @@ public struct Verifier {
}
@inline(__always)
func verify(id: String) throws {
func verify(id: String, at position: Int) throws {
let size = MemoryLayout<Int32>.size
guard storage.capacity >= (size &* 2) else {
guard
position >= 0,
position <= storage.capacity,
storage.capacity - position >= size &* 2
else {
throw FlatbuffersErrors.bufferDoesntContainID
}
let str = _buffer.readString(at: size, count: size)
let str = _buffer.readString(at: position &+ size, count: size)
if id == str {
return
}
@@ -30,7 +30,7 @@ struct _InternalByteBuffer {
@usableFromInline
final class Storage {
/// pointer to the start of the buffer object in memory
private(set) var memory: UnsafeMutableRawPointer
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
@usableFromInline
init(count: Int, alignment: Int) {
@@ -146,7 +146,7 @@ struct _InternalByteBuffer {
#if !os(WASI)
@inline(__always)
@usableFromInline
mutating func push(bytes: ContiguousBytes) {
mutating func push(bytes: any ContiguousBytes) {
bytes.withUnsafeBytes { ptr in
ensureSpace(size: ptr.count)
memcpy(
@@ -333,6 +333,7 @@ struct _InternalByteBuffer {
@discardableResult
@inline(__always)
@usableFromInline
func readWithUnsafeRawPointer<T>(
position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
+28 -11
View File
@@ -27,15 +27,32 @@ public struct ByteBuffer {
@usableFromInline
final class Storage {
@usableFromInline
enum Blob {
@frozen enum Blob: ~Copyable {
#if !os(WASI)
case data(Data)
case bytes(ContiguousBytes)
case bytes(any ContiguousBytes)
#endif
case byteBuffer(_InternalByteBuffer)
case array([UInt8])
case pointer(UnsafeMutableRawPointer)
init(_ other: borrowing Blob) {
switch other {
#if !os(WASI)
case .data(let data):
self = .data(data)
case .bytes(let contiguousBytes):
self = .bytes(contiguousBytes)
#endif
case .byteBuffer(let internalByteBuffer):
self = .byteBuffer(internalByteBuffer)
case .array(let array):
self = .array(array)
case .pointer(let unsafeMutableRawPointer):
self = .pointer(unsafeMutableRawPointer)
}
}
}
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -44,7 +61,7 @@ public struct ByteBuffer {
private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline
var retainedBlob: Blob
let retainedBlob: Blob
@usableFromInline
init(count: Int) {
@@ -57,9 +74,9 @@ public struct ByteBuffer {
}
@usableFromInline
init(blob: Blob, capacity count: Int) {
init(blob: borrowing Blob, capacity count: Int) {
capacity = count
retainedBlob = blob
retainedBlob = .init(blob)
isOwned = false
}
@@ -276,7 +293,7 @@ public struct ByteBuffer {
/// - removeBytes: Removes a number of bytes from the current size
@inline(__always)
init(
blob: Storage.Blob,
blob: borrowing Storage.Blob,
count: Int,
removing removeBytes: Int)
{
@@ -316,7 +333,7 @@ public struct ByteBuffer {
/// - def: Type of the object
/// - position: the index of the object in the buffer
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1)
.pointee
@@ -360,10 +377,10 @@ public struct ByteBuffer {
@inline(__always)
func readSizedScalar<
T: BinaryInteger,
T1: BinaryInteger,
T2: BinaryInteger,
T3: BinaryInteger,
T4: BinaryInteger
T1: BinaryInteger & BitwiseCopyable,
T2: BinaryInteger & BitwiseCopyable,
T3: BinaryInteger & BitwiseCopyable,
T4: BinaryInteger & BitwiseCopyable
>(
def: T.Type,
t1: T1.Type,
@@ -16,7 +16,7 @@
import Foundation
public enum FlexBufferType: UInt64 {
public enum FlexBufferType: UInt64, Sendable {
case null = 0
/// Variable width signed integer: `Int8, Int16, Int32, Int64`
case int = 1
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import Common
import Foundation
enum FlexBuffersErrors: Error {
@@ -23,6 +24,10 @@ enum FlexBuffersErrors: Error {
@inline(__always)
public func getRoot(buffer: ByteBuffer) throws -> Reference? {
assert(
isLitteEndian,
"Swift FlexBuffers currently only supports little-endian systems")
let end = buffer.count
if buffer.count < 3 {
throw FlexBuffersErrors.sizeOfBufferIsTooSmall
@@ -17,7 +17,7 @@
import Foundation
@usableFromInline
enum BitWidth: UInt64, CaseIterable {
enum BitWidth: UInt64, CaseIterable, Sendable {
case w8 = 0
case w16 = 1
case w32 = 2
+2 -2
View File
@@ -20,10 +20,10 @@ import Foundation
import Common
#endif
public struct Value: Equatable {
public struct Value: Equatable, Sendable {
@usableFromInline
enum Union: Equatable {
enum Union: Equatable, Sendable {
case i(Int64)
case u(UInt64)
case f(Double)
@@ -37,12 +37,15 @@ public struct FlexBuffersWriter {
private var hasDuplicatedKeys = false
private var minBitWidth: BitWidth = .w8
private var _bb: _InternalByteBuffer
private var stack: [Value] = []
private var stack: Stack = Stack()
private var keyPool: [Int: UInt] = [:]
private var stringPool: [Int: UInt] = [:]
private var flags: BuilderFlag
public init(initialSize: Int = 1024, flags: BuilderFlag = .shareKeys) {
assert(
isLitteEndian,
"Swift FlexBuffers currently only supports little-endian systems")
_bb = _InternalByteBuffer(initialSize: initialSize)
self.flags = flags
}
@@ -148,7 +151,7 @@ public struct FlexBuffersWriter {
typed: typed,
fixed: fixed,
keys: nil)
stack = Array(stack[..<start])
stack.popLast(start)
stack.append(vec)
return vec.u
}
@@ -217,7 +220,7 @@ public struct FlexBuffersWriter {
typed: false,
fixed: false,
keys: keys)
stack = Array(stack[..<start])
stack.popLast(start)
stack.append(vec)
return numericCast(vec.u)
}
@@ -721,7 +724,7 @@ public struct FlexBuffersWriter {
assert(
vectorType == stack[i].type,
"""
If you get this assert you are writing a typed vector
If you get this assert you are writing a typed vector
with elements that are not all the same type
""")
}
@@ -757,7 +760,7 @@ public struct FlexBuffersWriter {
}
if !fixed {
write(value: count, byteWidth: byteWidth)
write(value: UInt64(count), byteWidth: byteWidth)
}
let vloc = _bb.writerIndex
@@ -830,13 +833,14 @@ public struct FlexBuffersWriter {
let key, value: Value
}
stack[start...].withUnsafeMutableBytes { buffer in
stack.withUnsafeMutableBytes(start: start) { buffer in
var ptr = buffer.assumingMemoryBound(to: TwoValue.self)
ptr.sort { a, b in
let aMem = _bb.memory.advanced(by: numericCast(a.key.u))
.assumingMemoryBound(to: CChar.self)
let bMem = _bb.memory.advanced(by: numericCast(b.key.u))
.assumingMemoryBound(to: CChar.self)
let comp = strcmp(aMem, bMem)
if (comp == 0) && a != b { hasDuplicatedKeys = true }
return comp < 0
@@ -897,3 +901,132 @@ extension FlexBuffersWriter {
return endMap(start: start)
}
}
fileprivate struct Stack: RandomAccessCollection {
typealias Element = Value
typealias Index = Int
private final class Storage {
var memory: UnsafeMutableRawPointer
init(capacity: Int, alignment: Int) {
memory = .allocate(byteCount: capacity, alignment: alignment)
memset(memory, 0, capacity)
}
deinit {
memory.deallocate()
}
}
private static let initialCapacity = 10 &* MemoryLayout<Value>.stride
private let storage: Storage
private var capacity: Int
private(set) var count: Int
var startIndex: Int {
0
}
var endIndex: Int {
count
}
init() {
count = 0
capacity = Self.initialCapacity
storage = Storage(
capacity: capacity,
alignment: MemoryLayout<Value>.alignment)
}
@inline(__always)
subscript(position: Int) -> Value {
get {
storage.memory.advanced(by: position &* MemoryLayout<Value>.stride)
.assumingMemoryBound(to: Value.self).pointee
}
set {
storage.memory.advanced(by: position &* MemoryLayout<Value>.stride)
.assumingMemoryBound(to: Value.self).pointee = newValue
}
}
@inline(__always)
mutating func popLast(_ val: Int) {
count = if val < 0 {
0
} else {
val
}
}
mutating func append(_ value: Value) {
let writePosition = count &* MemoryLayout<Value>.stride
if writePosition >= capacity {
reallocate(writePosition: writePosition)
}
storage.memory.advanced(by: writePosition).storeBytes(
of: value,
as: Value.self)
count += 1
}
mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
count = 0
if !keepCapacity {
let ptr = storage.memory
defer { ptr.deallocate() }
capacity = Self.initialCapacity
storage.memory = UnsafeMutableRawPointer.allocate(
byteCount: capacity,
alignment: MemoryLayout<Value>.alignment)
}
memset(storage.memory, 0, capacity)
}
@discardableResult
mutating func withUnsafeMutableBytes<R>(
start: Int,
_ body: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R
{
let startingPosition = start &* MemoryLayout<Value>.stride
let pointer = storage.memory.advanced(by: startingPosition)
return try body(UnsafeMutableRawBufferPointer(
start: pointer,
count: (count &* MemoryLayout<Value>.stride) &- startingPosition))
}
@discardableResult
mutating func withUnsafeMutableBytes<R>(
_ body: (UnsafeMutableRawBufferPointer) throws
-> R) rethrows -> R
{
return try body(UnsafeMutableRawBufferPointer(
start: storage.memory,
count: count &* MemoryLayout<Value>.stride))
}
mutating private func reallocate(writePosition: Int) {
while capacity <= writePosition {
capacity = capacity << 1
}
/// solution take from Apple-NIO
capacity = capacity.convertToPowerofTwo
let newData = UnsafeMutableRawPointer.allocate(
byteCount: capacity,
alignment: MemoryLayout<Value>.alignment)
memset(newData, 0, capacity)
memcpy(
newData,
storage.memory,
writePosition)
storage.memory.deallocate()
storage.memory = newData
}
}
@@ -31,7 +31,7 @@ struct _InternalByteBuffer {
@usableFromInline
final class Storage {
/// pointer to the start of the buffer object in memory
var memory: UnsafeMutableRawPointer
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
@usableFromInline
init(count: Int, alignment: Int) {
@@ -60,7 +60,7 @@ struct _InternalByteBuffer {
let newData = UnsafeMutableRawPointer.allocate(
byteCount: capacity,
alignment: alignment)
memset(newData, 0, capacity &- writerSize)
memset(newData, 0, capacity)
memcpy(
newData,
memory,
+13 -17
View File
@@ -52,6 +52,7 @@ cc_test(
"monster_test.cpp",
"monster_test.h",
"monster_test_bfbs_generated.h",
"cross_namespace_pack_test_generated.h",
"namespace_test/namespace_test1_generated.h",
"namespace_test/namespace_test2_generated.h",
"native_inline_table_test_generated.h",
@@ -78,9 +79,6 @@ cc_test(
"vector_table_naked_ptr/vector_table_naked_ptr_generated.h",
"vector_table_naked_ptr_test.h",
"vector_table_naked_ptr_test.cpp",
"test_vector_type.h",
"cpp_vector_type_test.h",
"cpp_vector_type_test.cpp",
],
copts = [
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
@@ -139,7 +137,7 @@ cc_test(
deps = [
":alignment_test_cc_fbs",
":arrays_test_cc_fbs",
":cpp_vector_type_cc_fbs",
":cross_namespace_pack_test_cc_fbs",
":default_vectors_strings_test_cc_fbs",
":monster_extra_cc_fbs",
":monster_test_cc_fbs",
@@ -265,6 +263,17 @@ flatbuffer_cc_library(
],
)
flatbuffer_cc_library(
name = "cross_namespace_pack_test_cc_fbs",
srcs = ["cross_namespace_pack_test.fbs"],
flatc_args = [
"--gen-object-api",
"--gen-mutable",
"--gen-compare",
"--reflect-names",
],
)
flatbuffer_cc_library(
name = "native_type_test_cc_fbs",
srcs = ["native_type_test.fbs"],
@@ -275,19 +284,6 @@ flatbuffer_cc_library(
],
)
flatbuffer_cc_library(
name = "cpp_vector_type_cc_fbs",
srcs = ["cpp_vector_type.fbs"],
flatc_args = [
"--gen-compare",
"--gen-mutable",
"--gen-object-api",
"--reflect-names",
"--cpp-include test_vector_type.h",
"--cpp-vector-type ::flatbuffers::tests::CustomVector",
],
)
flatbuffer_cc_library(
name = "alignment_test_cc_fbs",
srcs = ["alignment_test.fbs"],
@@ -106,6 +106,9 @@
<Compile Include="..\MyGame\Example\NestedStruct.cs">
<Link>MyGame\Example\NestedStruct.cs</Link>
</Compile>
<Compile Include="..\MyGame\Example\LargeArrayStruct.cs">
<Link>MyGame\Example\LargeArrayStruct.cs</Link>
</Compile>
<Compile Include="..\MyGame\Example\LongEnum.cs">
<Link>MyGame\Example\LongEnum.cs</Link>
</Compile>
+20 -20
View File
@@ -922,7 +922,7 @@ def MonsterCreateInventoryVector(builder, data):
return builder.EndVector()
def CreateInventoryVector(builder, data):
MonsterCreateInventoryVector(builder, data)
return MonsterCreateInventoryVector(builder, data)
def MonsterAddColor(builder, color):
builder.PrependUint8Slot(6, color, 8)
@@ -962,7 +962,7 @@ def MonsterCreateTest4Vector(builder, data):
return builder.EndVector()
def CreateTest4Vector(builder, data):
MonsterCreateTest4Vector(builder, data)
return MonsterCreateTest4Vector(builder, data)
def MonsterAddTestarrayofstring(builder, testarrayofstring):
builder.PrependUOffsetTRelativeSlot(10, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofstring), 0)
@@ -980,7 +980,7 @@ def MonsterCreateTestarrayofstringVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateTestarrayofstringVector(builder, data):
MonsterCreateTestarrayofstringVector(builder, data)
return MonsterCreateTestarrayofstringVector(builder, data)
def MonsterAddTestarrayoftables(builder, testarrayoftables):
builder.PrependUOffsetTRelativeSlot(11, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayoftables), 0)
@@ -998,7 +998,7 @@ def MonsterCreateTestarrayoftablesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateTestarrayoftablesVector(builder, data):
MonsterCreateTestarrayoftablesVector(builder, data)
return MonsterCreateTestarrayoftablesVector(builder, data)
def MonsterAddEnemy(builder, enemy):
builder.PrependUOffsetTRelativeSlot(12, flatbuffers.number_types.UOffsetTFlags.py_type(enemy), 0)
@@ -1026,7 +1026,7 @@ def MonsterCreateTestnestedflatbufferVector(builder, data):
return builder.EndVector()
def CreateTestnestedflatbufferVector(builder, data):
MonsterCreateTestnestedflatbufferVector(builder, data)
return MonsterCreateTestnestedflatbufferVector(builder, data)
def MonsterMakeTestnestedflatbufferVectorFromBytes(builder, bytes):
builder.StartVector(1, len(bytes), 1)
@@ -1115,7 +1115,7 @@ def MonsterCreateTestarrayofboolsVector(builder, data):
return builder.EndVector()
def CreateTestarrayofboolsVector(builder, data):
MonsterCreateTestarrayofboolsVector(builder, data)
return MonsterCreateTestarrayofboolsVector(builder, data)
def MonsterAddTestf(builder, testf):
builder.PrependFloat32Slot(25, testf, 3.14159)
@@ -1151,7 +1151,7 @@ def MonsterCreateTestarrayofstring2Vector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateTestarrayofstring2Vector(builder, data):
MonsterCreateTestarrayofstring2Vector(builder, data)
return MonsterCreateTestarrayofstring2Vector(builder, data)
def MonsterAddTestarrayofsortedstruct(builder, testarrayofsortedstruct):
builder.PrependUOffsetTRelativeSlot(29, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofsortedstruct), 0)
@@ -1173,7 +1173,7 @@ def MonsterCreateTestarrayofsortedstructVector(builder, data):
return builder.EndVector()
def CreateTestarrayofsortedstructVector(builder, data):
MonsterCreateTestarrayofsortedstructVector(builder, data)
return MonsterCreateTestarrayofsortedstructVector(builder, data)
def MonsterAddFlex(builder, flex):
builder.PrependUOffsetTRelativeSlot(30, flatbuffers.number_types.UOffsetTFlags.py_type(flex), 0)
@@ -1195,7 +1195,7 @@ def MonsterCreateFlexVector(builder, data):
return builder.EndVector()
def CreateFlexVector(builder, data):
MonsterCreateFlexVector(builder, data)
return MonsterCreateFlexVector(builder, data)
def MonsterAddTest5(builder, test5):
builder.PrependUOffsetTRelativeSlot(31, flatbuffers.number_types.UOffsetTFlags.py_type(test5), 0)
@@ -1217,7 +1217,7 @@ def MonsterCreateTest5Vector(builder, data):
return builder.EndVector()
def CreateTest5Vector(builder, data):
MonsterCreateTest5Vector(builder, data)
return MonsterCreateTest5Vector(builder, data)
def MonsterAddVectorOfLongs(builder, vectorOfLongs):
builder.PrependUOffsetTRelativeSlot(32, flatbuffers.number_types.UOffsetTFlags.py_type(vectorOfLongs), 0)
@@ -1239,7 +1239,7 @@ def MonsterCreateVectorOfLongsVector(builder, data):
return builder.EndVector()
def CreateVectorOfLongsVector(builder, data):
MonsterCreateVectorOfLongsVector(builder, data)
return MonsterCreateVectorOfLongsVector(builder, data)
def MonsterAddVectorOfDoubles(builder, vectorOfDoubles):
builder.PrependUOffsetTRelativeSlot(33, flatbuffers.number_types.UOffsetTFlags.py_type(vectorOfDoubles), 0)
@@ -1261,7 +1261,7 @@ def MonsterCreateVectorOfDoublesVector(builder, data):
return builder.EndVector()
def CreateVectorOfDoublesVector(builder, data):
MonsterCreateVectorOfDoublesVector(builder, data)
return MonsterCreateVectorOfDoublesVector(builder, data)
def MonsterAddParentNamespaceTest(builder, parentNamespaceTest):
builder.PrependUOffsetTRelativeSlot(34, flatbuffers.number_types.UOffsetTFlags.py_type(parentNamespaceTest), 0)
@@ -1285,7 +1285,7 @@ def MonsterCreateVectorOfReferrablesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateVectorOfReferrablesVector(builder, data):
MonsterCreateVectorOfReferrablesVector(builder, data)
return MonsterCreateVectorOfReferrablesVector(builder, data)
def MonsterAddSingleWeakReference(builder, singleWeakReference):
builder.PrependUint64Slot(36, singleWeakReference, 0)
@@ -1313,7 +1313,7 @@ def MonsterCreateVectorOfWeakReferencesVector(builder, data):
return builder.EndVector()
def CreateVectorOfWeakReferencesVector(builder, data):
MonsterCreateVectorOfWeakReferencesVector(builder, data)
return MonsterCreateVectorOfWeakReferencesVector(builder, data)
def MonsterAddVectorOfStrongReferrables(builder, vectorOfStrongReferrables):
builder.PrependUOffsetTRelativeSlot(38, flatbuffers.number_types.UOffsetTFlags.py_type(vectorOfStrongReferrables), 0)
@@ -1331,7 +1331,7 @@ def MonsterCreateVectorOfStrongReferrablesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateVectorOfStrongReferrablesVector(builder, data):
MonsterCreateVectorOfStrongReferrablesVector(builder, data)
return MonsterCreateVectorOfStrongReferrablesVector(builder, data)
def MonsterAddCoOwningReference(builder, coOwningReference):
builder.PrependUint64Slot(39, coOwningReference, 0)
@@ -1359,7 +1359,7 @@ def MonsterCreateVectorOfCoOwningReferencesVector(builder, data):
return builder.EndVector()
def CreateVectorOfCoOwningReferencesVector(builder, data):
MonsterCreateVectorOfCoOwningReferencesVector(builder, data)
return MonsterCreateVectorOfCoOwningReferencesVector(builder, data)
def MonsterAddNonOwningReference(builder, nonOwningReference):
builder.PrependUint64Slot(41, nonOwningReference, 0)
@@ -1387,7 +1387,7 @@ def MonsterCreateVectorOfNonOwningReferencesVector(builder, data):
return builder.EndVector()
def CreateVectorOfNonOwningReferencesVector(builder, data):
MonsterCreateVectorOfNonOwningReferencesVector(builder, data)
return MonsterCreateVectorOfNonOwningReferencesVector(builder, data)
def MonsterAddAnyUniqueType(builder, anyUniqueType):
builder.PrependUint8Slot(43, anyUniqueType, 0)
@@ -1433,7 +1433,7 @@ def MonsterCreateVectorOfEnumsVector(builder, data):
return builder.EndVector()
def CreateVectorOfEnumsVector(builder, data):
MonsterCreateVectorOfEnumsVector(builder, data)
return MonsterCreateVectorOfEnumsVector(builder, data)
def MonsterAddSignedEnum(builder, signedEnum):
builder.PrependInt8Slot(48, signedEnum, -1)
@@ -1461,7 +1461,7 @@ def MonsterCreateTestrequirednestedflatbufferVector(builder, data):
return builder.EndVector()
def CreateTestrequirednestedflatbufferVector(builder, data):
MonsterCreateTestrequirednestedflatbufferVector(builder, data)
return MonsterCreateTestrequirednestedflatbufferVector(builder, data)
def MonsterMakeTestrequirednestedflatbufferVectorFromBytes(builder, bytes):
builder.StartVector(1, len(bytes), 1)
@@ -1486,7 +1486,7 @@ def MonsterCreateScalarKeySortedTablesVector(builder, data):
return builder.CreateVectorOfTables(data)
def CreateScalarKeySortedTablesVector(builder, data):
MonsterCreateScalarKeySortedTablesVector(builder, data)
return MonsterCreateScalarKeySortedTablesVector(builder, data)
def MonsterAddNativeInline(builder, nativeInline):
builder.PrependStructSlot(51, flatbuffers.number_types.UOffsetTFlags.py_type(nativeInline), 0)
+2 -2
View File
@@ -238,7 +238,7 @@ def TypeAliasesCreateV8Vector(builder, data):
return builder.EndVector()
def CreateV8Vector(builder, data):
TypeAliasesCreateV8Vector(builder, data)
return TypeAliasesCreateV8Vector(builder, data)
def TypeAliasesAddVf64(builder, vf64):
builder.PrependUOffsetTRelativeSlot(11, flatbuffers.number_types.UOffsetTFlags.py_type(vf64), 0)
@@ -260,7 +260,7 @@ def TypeAliasesCreateVf64Vector(builder, data):
return builder.EndVector()
def CreateVf64Vector(builder, data):
TypeAliasesCreateVf64Vector(builder, data)
return TypeAliasesCreateVf64Vector(builder, data)
def TypeAliasesEnd(builder):
return builder.EndObject()
+2 -2
View File
@@ -214,7 +214,7 @@ def MonsterExtraCreateDvecVector(builder: flatbuffers.Builder, data: Iterable[An
return builder.EndVector()
def CreateDvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
MonsterExtraCreateDvecVector(builder, data)
return MonsterExtraCreateDvecVector(builder, data)
def MonsterExtraAddFvec(builder: flatbuffers.Builder, fvec: int):
builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(fvec), 0)
@@ -236,7 +236,7 @@ def MonsterExtraCreateFvecVector(builder: flatbuffers.Builder, data: Iterable[An
return builder.EndVector()
def CreateFvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
MonsterExtraCreateFvecVector(builder, data)
return MonsterExtraCreateFvecVector(builder, data)
def MonsterExtraEnd(builder: flatbuffers.Builder) -> int:
return builder.EndObject()
+1
View File
@@ -28,6 +28,7 @@ ${test_dir}/../flatc -p -o ${gen_code_path} -I include_test monster_extra.fbs --
${test_dir}/../flatc -p -o ${gen_code_path} -I include_test arrays_test.fbs --gen-object-api --python-typing
${test_dir}/../flatc -p -o ${gen_code_path} -I include_test nested_union_test.fbs --gen-object-api --python-typing --python-decode-obj-api-strings
${test_dir}/../flatc -p -o ${gen_code_path} -I include_test service_test.fbs --grpc --grpc-python-typed-handlers --python-typing --no-python-gen-numpy --gen-onefile
${test_dir}/../flatc -p -o ${gen_code_path} union_name_test.fbs --gen-object-api
# Syntax: run_tests <interpreter> <benchmark vtable dedupes>
# <benchmark read count> <benchmark build count>
Binary file not shown.
+8
View File
@@ -18,6 +18,14 @@ struct ArrayStruct{
f:[int64:2];
}
struct LargeArrayStruct {
d:[ubyte:64];
e:[float:64];
f:[bool:64];
g:[NestedStruct:64];
h:[TestEnum:64];
}
table ArrayTable{
a:ArrayStruct;
}
+31
View File
@@ -59,6 +59,37 @@
},
"additionalProperties" : false
},
"MyGame_Example_LargeArrayStruct" : {
"type" : "object",
"properties" : {
"d" : {
"type" : "array", "items" : {"type" : "integer", "minimum" : 0, "maximum" :255},
"minItems": 64,
"maxItems": 64
},
"e" : {
"type" : "array", "items" : {"type" : "number"},
"minItems": 64,
"maxItems": 64
},
"f" : {
"type" : "array", "items" : {"type" : "boolean"},
"minItems": 64,
"maxItems": 64
},
"g" : {
"type" : "array", "items" : {"$ref" : "#/definitions/MyGame_Example_NestedStruct"},
"minItems": 64,
"maxItems": 64
},
"h" : {
"type" : "array", "items" : {"$ref" : "#/definitions/MyGame_Example_TestEnum"},
"minItems": 64,
"maxItems": 64
}
},
"additionalProperties" : false
},
"MyGame_Example_ArrayTable" : {
"type" : "object",
"properties" : {
+13 -11
View File
@@ -1,16 +1,18 @@
// Automatically generated by the Flatbuffers compiler. Do not modify.
// @generated
pub mod my_game {
use super::*;
pub mod example {
use super::*;
mod test_enum_generated;
pub use self::test_enum_generated::*;
mod nested_struct_generated;
pub use self::nested_struct_generated::*;
mod array_struct_generated;
pub use self::array_struct_generated::*;
mod array_table_generated;
pub use self::array_table_generated::*;
} // example
pub mod example {
use super::*;
mod test_enum_generated;
pub use self::test_enum_generated::*;
mod nested_struct_generated;
pub use self::nested_struct_generated::*;
mod array_struct_generated;
pub use self::array_struct_generated::*;
mod large_array_struct_generated;
pub use self::large_array_struct_generated::*;
mod array_table_generated;
pub use self::array_table_generated::*;
} // example
} // my_game

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