Compare commits

..

4 Commits

Author SHA1 Message Date
rboullard 5b7f602ea8 bigfoot_ref 2026-07-31 02:43:43 +02:00
rboullard a06c41f2c7 Simplify templates 2026-07-29 23:11:48 +02:00
rboullard 4f6ad45b0e templated type 2026-07-29 22:57:58 +02:00
rboullard 81e5f093f9 vector-type 2026-07-29 14:38:13 +02:00
292 changed files with 20530 additions and 27741 deletions
-6
View File
@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+13 -13
View File
@@ -42,7 +42,7 @@ jobs:
chmod +x flatc chmod +x flatc
./flatc --version ./flatc --version
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
with: with:
name: Linux flatc binary ${{ matrix.cxx }} name: Linux flatc binary ${{ matrix.cxx }}
path: flatc path: flatc
@@ -170,7 +170,7 @@ jobs:
- name: test - name: test
run: Release\flattests.exe run: Release\flattests.exe
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
with: with:
name: Windows flatc binary name: Windows flatc binary
path: Release\flatc.exe path: Release\flatc.exe
@@ -191,7 +191,7 @@ jobs:
build-dotnet-windows: build-dotnet-windows:
name: Build .NET Windows name: Build .NET Windows
runs-on: windows-2022 runs-on: windows-2022-64core
strategy: strategy:
matrix: matrix:
configuration: [ configuration: [
@@ -246,7 +246,7 @@ jobs:
chmod +x Release/flatc chmod +x Release/flatc
Release/flatc --version Release/flatc --version
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
with: with:
name: Mac flatc binary Intel name: Mac flatc binary Intel
path: Release/flatc path: Release/flatc
@@ -289,7 +289,7 @@ jobs:
chmod +x Release/flatc chmod +x Release/flatc
Release/flatc --version Release/flatc --version
- name: upload build artifacts - name: upload build artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
with: with:
name: Mac flatc binary Universal name: Mac flatc binary Universal
path: Release/flatc path: Release/flatc
@@ -314,7 +314,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: set up Java - name: set up Java
uses: actions/setup-java@v5 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
java-version: 17 java-version: 17
@@ -373,7 +373,7 @@ jobs:
- name: Run benchmarks - name: Run benchmarks
run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}} run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}}
- name: Upload benchmarks results - name: Upload benchmarks results
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
with: with:
name: Linux flatbenchmark results ${{matrix.cxx}} name: Linux flatbenchmark results ${{matrix.cxx}}
path: benchmarks/results_${{matrix.cxx}} path: benchmarks/results_${{matrix.cxx}}
@@ -394,7 +394,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: set up Java - name: set up Java
uses: actions/setup-java@v5 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
java-version: 17 java-version: 17
@@ -417,7 +417,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: set up Java - name: set up Java
uses: actions/setup-java@v5 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
java-version: 17 java-version: 17
@@ -446,7 +446,7 @@ jobs:
build-rust-windows: build-rust-windows:
name: Build Rust Windows name: Build Rust Windows
runs-on: windows-2022 runs-on: windows-2022-64core
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: test - name: test
@@ -495,7 +495,7 @@ jobs:
name: Test Swift Linux name: Test Swift Linux
strategy: strategy:
matrix: matrix:
swift: ["6.0", "6.1", "6.2"] swift: ["5.10", "6.1", "6.2"]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
@@ -534,7 +534,7 @@ jobs:
run: | run: |
swift sdk list swift sdk list
swift build --build-tests --swift-sdk swift-6.2.1-RELEASE_wasm swift build --build-tests --swift-sdk swift-6.2.1-RELEASE_wasm
wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest --testing-library swift-testing wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest
build-ts: build-ts:
name: Build TS name: Build TS
@@ -545,7 +545,7 @@ jobs:
# FIXME: make test script not rely on flatc # FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm - name: pnpm
run: npm install -g pnpm@10 run: npm install -g pnpm esbuild
- name: deps - name: deps
run: pnpm i run: pnpm i
- name: compile - name: compile
+2 -2
View File
@@ -21,11 +21,11 @@ jobs:
run: | run: |
git config user.name github-actions[bot] git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v6 - uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v5 - uses: actions/cache@v4
with: with:
key: mkdocs-material-${{ env.cache_id }} key: mkdocs-material-${{ env.cache_id }}
path: .cache path: .cache
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
language: c++ language: c++
fuzz-seconds: 60 fuzz-seconds: 60
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success' if: failure() && steps.build.outcome == 'success'
with: with:
name: artifacts name: artifacts
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- uses: actions/setup-node@v6 - uses: actions/setup-node@v3
with: with:
node-version: '20.x' node-version: '20.x'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
@@ -30,7 +30,7 @@ jobs:
working-directory: ./python working-directory: ./python
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 - uses: actions/setup-python@v4
with: with:
python-version: '3.10' python-version: '3.10'
+8 -1
View File
@@ -238,8 +238,13 @@ set(FlatBuffers_Tests_SRCS
tests/util_test.cpp tests/util_test.cpp
tests/vector_table_naked_ptr_test.h tests/vector_table_naked_ptr_test.h
tests/vector_table_naked_ptr_test.cpp 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.h
tests/native_type_test_impl.cpp tests/native_type_test_impl.cpp
tests/bigfoot_ref_test_impl.h
tests/bigfoot_ref_test_impl.cpp
tests/alignment_test.h tests/alignment_test.h
tests/alignment_test.cpp tests/alignment_test.cpp
tests/64bit/offset64_test.h tests/64bit/offset64_test.h
@@ -548,18 +553,20 @@ if(FLATBUFFERS_BUILD_TESTS)
# The flattest target needs some generated files # The flattest target needs some generated files
SET(FLATC_OPT_COMP --cpp --gen-compare --gen-mutable --gen-object-api --reflect-names) 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_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(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_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/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_inline_table_test.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/native_type_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/key_field/key_field_sample.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/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/v1.fbs "${FLATC_OPT_COMP}")
compile_schema_for_test(tests/64bit/evolution/v2.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/union_underlying_type_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
compile_schema_for_test(tests/cross_namespace_pack_test.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/cpp_vector_type.fbs "${FLATC_OPT_CPP_VECTOR_TYPE}")
if(FLATBUFFERS_CODE_SANITIZE) if(FLATBUFFERS_CODE_SANITIZE)
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE}) add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
+5 -2
View File
@@ -23,7 +23,7 @@ bazel_dep(
) )
bazel_dep( bazel_dep(
name = "grpc", name = "grpc",
version = "1.76.0", version = "1.70.1",
repo_name = "com_github_grpc_grpc", repo_name = "com_github_grpc_grpc",
) )
bazel_dep( bazel_dep(
@@ -49,7 +49,7 @@ bazel_dep(
) )
bazel_dep( bazel_dep(
name = "rules_swift", name = "rules_swift",
version = "3.1.2", version = "2.1.1",
max_compatibility_level = 3, max_compatibility_level = 3,
repo_name = "build_bazel_rules_swift", repo_name = "build_bazel_rules_swift",
) )
@@ -63,6 +63,9 @@ npm.npm_translate_lock(
name = "flatbuffers_npm", name = "flatbuffers_npm",
npmrc = "//:.npmrc", npmrc = "//:.npmrc",
pnpm_lock = "//ts:pnpm-lock.yaml", 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", verify_node_modules_ignored = "//:.bazelignore",
) )
use_repo(npm, "flatbuffers_npm") use_repo(npm, "flatbuffers_npm")
+7 -25
View File
@@ -1,4 +1,4 @@
// swift-tools-version:6.0 // swift-tools-version:5.10
/* /*
* Copyright 2020 Google Inc. All rights reserved. * Copyright 2020 Google Inc. All rights reserved.
* *
@@ -36,17 +36,14 @@ let package = Package(
.target( .target(
name: "FlatBuffers", name: "FlatBuffers",
dependencies: ["Common"], dependencies: ["Common"],
path: "swift/Sources/FlatBuffers", path: "swift/Sources/FlatBuffers"),
swiftSettings: .settings),
.target( .target(
name: "FlexBuffers", name: "FlexBuffers",
dependencies: ["Common"], dependencies: ["Common"],
path: "swift/Sources/FlexBuffers", path: "swift/Sources/FlexBuffers"),
swiftSettings: .settings),
.target( .target(
name: "Common", name: "Common",
path: "swift/Sources/Common", path: "swift/Sources/Common"),
swiftSettings: .settings),
.testTarget( .testTarget(
name: "FlatbuffersTests", name: "FlatbuffersTests",
dependencies: .dependencies, dependencies: .dependencies,
@@ -55,14 +52,7 @@ let package = Package(
name: "FlexbuffersTests", name: "FlexbuffersTests",
dependencies: ["FlexBuffers"], dependencies: ["FlexBuffers"],
path: "tests/swift/Tests/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 { extension Array where Element == Package.Dependency {
static var dependencies: [Package.Dependency] { static var dependencies: [Package.Dependency] {
@@ -70,12 +60,7 @@ extension Array where Element == Package.Dependency {
[] []
#else #else
// Test only Dependency // 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"),
]
#endif #endif
} }
} }
@@ -87,10 +72,7 @@ extension Array where Element == PackageDescription.Target.Dependency {
#else #else
// Test only Dependency // Test only Dependency
[ [
.product(name: "GRPCCore", package: "grpc-swift-2"), .product(name: "GRPC", package: "grpc-swift"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
"FlatBuffers", "FlatBuffers",
] ]
#endif #endif
@@ -97,7 +97,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB))) blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
} }
benchmark.stopMeasurement()
} }
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
@@ -106,7 +105,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.clear()) blackHole(fb.clear())
} }
benchmark.stopMeasurement()
} }
Benchmark("Strings 10") { benchmark in Benchmark("Strings 10") { benchmark in
@@ -115,7 +113,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10)) blackHole(fb.create(string: str10))
} }
benchmark.stopMeasurement()
} }
Benchmark("Strings 100") { benchmark in Benchmark("Strings 100") { benchmark in
@@ -124,7 +121,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100)) blackHole(fb.create(string: str100))
} }
benchmark.stopMeasurement()
} }
Benchmark("Vector 1 Bytes") { benchmark in Benchmark("Vector 1 Bytes") { benchmark in
@@ -133,7 +129,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes)) blackHole(fb.createVector(bytes: bytes))
} }
benchmark.stopMeasurement()
} }
Benchmark("Vector 1 Ints") { benchmark in Benchmark("Vector 1 Ints") { benchmark in
@@ -142,7 +137,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints)) blackHole(fb.createVector(ints))
} }
benchmark.stopMeasurement()
} }
Benchmark("Vector 100 Ints") { benchmark in Benchmark("Vector 100 Ints") { benchmark in
@@ -151,7 +145,6 @@ let benchmarks = {
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints)) blackHole(fb.createVector(ints))
} }
benchmark.stopMeasurement()
} }
Benchmark("Vector 100 Bytes") { benchmark in Benchmark("Vector 100 Bytes") { benchmark in
@@ -160,7 +153,6 @@ let benchmarks = {
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes)) blackHole(fb.createVector(bytes))
} }
benchmark.stopMeasurement()
} }
Benchmark("Vector 100 ContiguousBytes") { benchmark in Benchmark("Vector 100 ContiguousBytes") { benchmark in
@@ -169,7 +161,6 @@ let benchmarks = {
for i in benchmark.scaledIterations { for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes)) blackHole(fb.createVector(bytes: bytes))
} }
benchmark.stopMeasurement()
} }
Benchmark( Benchmark(
@@ -187,7 +178,6 @@ let benchmarks = {
fb.add(offset: off, at: 8) fb.add(offset: off, at: 8)
blackHole(fb.endTable(at: s)) blackHole(fb.endTable(at: s))
} }
benchmark.stopMeasurement()
} }
Benchmark( Benchmark(
@@ -200,7 +190,6 @@ let benchmarks = {
let s = fb.startTable(with: 4) let s = fb.startTable(with: 4)
blackHole(fb.endTable(at: s)) blackHole(fb.endTable(at: s))
} }
benchmark.stopMeasurement()
} }
Benchmark("Struct") { benchmark in Benchmark("Struct") { benchmark in
@@ -209,7 +198,6 @@ let benchmarks = {
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(fb.create(struct: array.first!)) blackHole(fb.create(struct: array.first!))
} }
benchmark.stopMeasurement()
} }
Benchmark("Structs") { benchmark in Benchmark("Structs") { benchmark in
@@ -231,7 +219,6 @@ let benchmarks = {
fb.add(offset: vector, at: 4) fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start)) let root = Offset(offset: fb.endTable(at: start))
blackHole(fb.finish(offset: root)) blackHole(fb.finish(offset: root))
benchmark.stopMeasurement()
} }
Benchmark("Vector of Offsets") { benchmark in Benchmark("Vector of Offsets") { benchmark in
@@ -252,15 +239,12 @@ let benchmarks = {
fb.add(offset: off, at: 2) fb.add(offset: off, at: 2)
blackHole(fb.endTable(at: s)) blackHole(fb.endTable(at: s))
} }
benchmark.stopMeasurement()
} }
Benchmark("Reading Doubles") { benchmark in Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data) let byteBuffer = ByteBuffer(data: data)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations { for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0)) blackHole(byteBuffer.read(def: Double.self, position: 0))
} }
benchmark.stopMeasurement()
} }
} }
@@ -1,174 +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 Benchmark
import FlexBuffers
import Foundation
let benchmarks = {
let data = {
var array = [8888.88, 8888.88]
var data = Data()
array.withUnsafeBytes { ptr in
data.append(contentsOf: ptr)
}
return data
}()
let ints: [Int32] = Array(repeating: 42, count: 100)
let str10 = (0...9).map { _ -> String in "x" }.joined()
let str100 = (0...99).map { _ -> String in "x" }.joined()
// A representative map: 50 keyed scalars, a keyed string and a keyed vector
// of 100 scalars. Used for the realistic decode benchmarks.
let mapBuffer: ByteBuffer = {
var fbx = FlexBuffersWriter(initialSize: 1 << 16)
fbx.map {
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
$0.add(string: "hello world", key: "s")
$0.vector(key: "v") { v in
for x in 0..<100 { v.add(int: x) }
}
}
fbx.finish()
return fbx.sizedByteBuffer
}()
let metrics: [BenchmarkMetric] = [
.cpuTotal,
.wallClock,
.mallocCountTotal,
.releaseCount,
.peakMemoryResident,
]
let maxIterations = 1_000_000
let maxDuration: Duration = .seconds(3)
let megaConfiguration: Benchmark.Configuration = .init(
metrics: metrics,
warmupIterations: 1,
scalingFactor: .mega,
maxDuration: maxDuration,
maxIterations: maxIterations)
Benchmark.defaultConfiguration = megaConfiguration
// Decode (read path)
// Raw scalar read: isolates `read<T: BitwiseCopyable>` and the `let` blob.
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()
}
// Realistic decode: resolve root map and read a keyed scalar.
Benchmark("Decode Map Scalar") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
blackHole(map["i25"]?.int)
}
benchmark.stopMeasurement()
}
// Realistic decode: resolve root map and read a keyed string.
Benchmark("Decode Map String") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
blackHole(map["s"]?.string())
}
benchmark.stopMeasurement()
}
// Realistic decode: resolve a nested vector and sum its scalars.
Benchmark("Decode Vector") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
let vector = map["v"]!.vector!
var sum: Int64 = 0
for i in 0..<vector.count {
sum &+= vector[i]?.int ?? 0
}
blackHole(sum)
}
benchmark.stopMeasurement()
}
// Encode (write path)
// Writers are reused with `reset(keepingCapacity:)` so per-iteration
// allocation does not dominate and mask the write-path cost (which is what
// the `@exclusivity(unchecked)` storage pointer affects).
Benchmark("Strings 10") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.add(string: str10)
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Strings 100") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.add(string: str100)
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Encoding Vector Of Ints") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.vector {
$0.create(vector: ints)
}
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Encoding Map") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.map {
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
$0.add(string: "hello world", key: "s")
$0.vector(key: "v") { v in
for x in 0..<100 { v.add(int: x) }
}
}
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
}
-10
View File
@@ -39,14 +39,4 @@ let package = Package(
plugins: [ plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"), .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"),
]),
]) ])
+1 -2
View File
@@ -5,7 +5,7 @@ import 'types.dart';
/// The main builder class for creation of a FlexBuffer. /// The main builder class for creation of a FlexBuffer.
class Builder { class Builder {
ByteData _buffer; final ByteData _buffer;
List<_StackValue> _stack = []; List<_StackValue> _stack = [];
List<_StackPointer> _stackPointers = []; List<_StackPointer> _stackPointers = [];
int _offset = 0; int _offset = 0;
@@ -506,7 +506,6 @@ class Builder {
if (prevSize < size) { if (prevSize < size) {
final newBuf = ByteData(size); final newBuf = ByteData(size);
newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List()); newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List());
_buffer = newBuf;
} }
return newOffset; return newOffset;
} }
-15
View File
@@ -318,21 +318,6 @@ void main() {
1, 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', () { test('build map', () {
+6
View File
@@ -168,6 +168,12 @@ list of `FILES...`.
std::string from Flatbuffers, but (char* + length). This allows efficient std::string from Flatbuffers, but (char* + length). This allows efficient
construction of custom string types, including zero-copy construction. 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++ - `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
object-based API. object-based API.
+58 -1
View File
@@ -57,7 +57,7 @@ a `char *` array, which you pass to `GetMonster()`.
```cpp ```cpp
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "monster_test_generated.h" #include "monster_test_generate.h"
#include <iostream> // C++ header file for printing #include <iostream> // C++ header file for printing
#include <fstream> // C++ header file for file access #include <fstream> // C++ header file for file access
@@ -242,6 +242,42 @@ 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_type("type")` (on a table): Tables can also be represented with
native types. For example, the following schema: native types. For example, the following schema:
@@ -337,6 +373,27 @@ 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, 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. 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) ## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to There is experimental support for reflection in FlatBuffers, allowing you to
-96
View File
@@ -97,61 +97,6 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
*Note: That we never stored a `mana` value, so it will return the default.* *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 ## Direct memory access
As you can see from the above examples, all elements in a buffer are As you can see from the above examples, all elements in a buffer are
@@ -260,47 +205,6 @@ 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), - 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 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 ## Useful tools created by others
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler * [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
+3
View File
@@ -427,6 +427,9 @@ Current understood attributes:
it won't be accessible anymore by newer code. Note that if you deprecate a 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 field that was previous required, old code may fail to validate new data (when
using the optional verifier). using the optional verifier).
### `required`
- `required` (on a non-scalar table field): this field must always be set. By - `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 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 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 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 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 Native Object API | Yes | No | Yes | Yes | Yes | Yes | Yes | No | No | Yes | No | No | Yes
Optional Scalars | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes Optional Scalars | Yes | Yes | Yes | No | No | Yes | Yes | Yes | No | No | Yes | Yes | Yes
Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | Yes Flexbuffers | Yes | Yes | ? | ? | ? | ? | ? | ? | ? | ? | ? | Yes | Yes
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | 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 Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
+268 -293
View File
@@ -1,322 +1,297 @@
// automatically generated by the FlatBuffers compiler, do not modify // automatically generated by the FlatBuffers compiler, do not modify
// @generated // @generated
extern crate alloc; extern crate alloc;
#[allow(unused_imports, dead_code)] #[allow(unused_imports, dead_code)]
pub mod flatbuffers { pub mod flatbuffers {
extern crate alloc;
#[allow(unused_imports, dead_code)] extern crate alloc;
pub mod goldens { #[allow(unused_imports, dead_code)]
extern crate alloc; pub mod goldens {
pub enum GalaxyOffset {} extern crate alloc;
#[derive(Copy, Clone, PartialEq)] pub enum GalaxyOffset {}
pub struct Galaxy<'a> { #[derive(Copy, Clone, PartialEq)]
pub _tab: ::flatbuffers::Table<'a>,
}
impl<'a> ::flatbuffers::Follow<'a> for Galaxy<'a> { pub struct Galaxy<'a> {
type Inner = Galaxy<'a>; pub _tab: ::flatbuffers::Table<'a>,
}
#[inline] impl<'a> ::flatbuffers::Follow<'a> for Galaxy<'a> {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { type Inner = Galaxy<'a>;
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> { impl<'a> Galaxy<'a> {
pub const VT_NUM_STARS: ::flatbuffers::VOffsetT = 4; pub const VT_NUM_STARS: ::flatbuffers::VOffsetT = 4;
#[inline] #[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Galaxy { _tab: table } Galaxy { _tab: table }
} }
#[allow(unused_mut)]
#[allow(unused_mut)] pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>(
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>,
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, args: &'args GalaxyArgs
args: &'args GalaxyArgs ) -> ::flatbuffers::WIPOffset<Galaxy<'bldr>> {
) -> ::flatbuffers::WIPOffset<Galaxy<'bldr>> { let mut builder = GalaxyBuilder::new(_fbb);
let mut builder = GalaxyBuilder::new(_fbb); builder.add_num_stars(args.num_stars);
builder.add_num_stars(args.num_stars); builder.finish()
builder.finish() }
}
#[inline] #[inline]
pub fn num_stars(&self) -> i64 { pub fn num_stars(&self) -> i64 {
// Safety: // Safety:
// Created from valid Table for this object // Created from valid Table for this object
// which contains a valid value in this slot // which contains a valid value in this slot
unsafe { self._tab.get::<i64>(Galaxy::VT_NUM_STARS, Some(0)).unwrap()} unsafe { self._tab.get::<i64>(Galaxy::VT_NUM_STARS, Some(0)).unwrap()}
} }
} }
impl ::flatbuffers::Verifiable for Galaxy<'_> { impl ::flatbuffers::Verifiable for Galaxy<'_> {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)? v.visit_table(pos)?
.visit_field::<i64>("num_stars", Self::VT_NUM_STARS, false)? .visit_field::<i64>("num_stars", Self::VT_NUM_STARS, false)?
.finish(); .finish();
Ok(()) Ok(())
} }
} }
pub struct GalaxyArgs {
pub num_stars: i64,
}
impl<'a> Default for GalaxyArgs {
#[inline]
fn default() -> Self {
GalaxyArgs {
num_stars: 0,
}
}
}
pub struct GalaxyArgs { pub struct GalaxyBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
pub num_stars: i64, 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())
}
}
impl<'a> Default for GalaxyArgs { impl ::core::fmt::Debug for Galaxy<'_> {
#[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
fn default() -> Self { let mut ds = f.debug_struct("Galaxy");
GalaxyArgs { ds.field("num_stars", &self.num_stars());
num_stars: 0, ds.finish()
} }
} }
} pub enum UniverseOffset {}
#[derive(Copy, Clone, PartialEq)]
pub struct GalaxyBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { pub struct Universe<'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, pub _tab: ::flatbuffers::Table<'a>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, }
}
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GalaxyBuilder<'a, 'b, A> { impl<'a> ::flatbuffers::Follow<'a> for Universe<'a> {
#[inline] type Inner = Universe<'a>;
pub fn add_num_stars(&mut self, num_stars: i64) { #[inline]
self.fbb_.push_slot::<i64>(Galaxy::VT_NUM_STARS, num_stars, 0); unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
} Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
}
}
#[inline] impl<'a> Universe<'a> {
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> GalaxyBuilder<'a, 'b, A> { pub const VT_AGE: ::flatbuffers::VOffsetT = 4;
let start = _fbb.start_table(); pub const VT_GALAXIES: ::flatbuffers::VOffsetT = 6;
GalaxyBuilder {
fbb_: _fbb,
start_: start,
}
}
#[inline] #[inline]
pub fn finish(self) -> ::flatbuffers::WIPOffset<Galaxy<'a>> { pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
let o = self.fbb_.end_table(self.start_); Universe { _tab: table }
::flatbuffers::WIPOffset::new(o.value()) }
} #[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>,
impl ::core::fmt::Debug for Galaxy<'_> { args: &'args UniverseArgs<'args>
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { ) -> ::flatbuffers::WIPOffset<Universe<'bldr>> {
let mut ds = f.debug_struct("Galaxy"); let mut builder = UniverseBuilder::new(_fbb);
ds.field("num_stars", &self.num_stars()); builder.add_age(args.age);
ds.finish() if let Some(x) = args.galaxies { builder.add_galaxies(x); }
} builder.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] #[inline]
pub fn age(&self) -> f64 { pub fn age(&self) -> f64 {
// Safety: // Safety:
// Created from valid Table for this object // Created from valid Table for this object
// which contains a valid value in this slot // which contains a valid value in this slot
unsafe { self._tab.get::<f64>(Universe::VT_AGE, Some(0.0)).unwrap()} 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] impl ::flatbuffers::Verifiable for Universe<'_> {
pub fn galaxies(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>> { #[inline]
// Safety: fn run_verifier(
// Created from valid Table for this object v: &mut ::flatbuffers::Verifier, pos: usize
// which contains a valid value in this slot ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy>>>>(Universe::VT_GALAXIES, None)} 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,
}
}
}
impl ::flatbuffers::Verifiable for Universe<'_> { pub struct UniverseBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
#[inline] fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
fn run_verifier( start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
v: &mut ::flatbuffers::Verifier, pos: usize }
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> UniverseBuilder<'a, 'b, A> {
v.visit_table(pos)? #[inline]
.visit_field::<f64>("age", Self::VT_AGE, false)? pub fn add_age(&mut self, age: f64) {
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Galaxy>>>>("galaxies", Self::VT_GALAXIES, false)? self.fbb_.push_slot::<f64>(Universe::VT_AGE, age, 0.0);
.finish(); }
Ok(()) #[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())
}
}
pub struct UniverseArgs<'a> { impl ::core::fmt::Debug for Universe<'_> {
pub age: f64, fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
pub galaxies: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset<Galaxy<'a>>>>>, 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);
}
impl<'a> Default for UniverseArgs<'a> { #[inline]
#[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>>) {
fn default() -> Self { fbb.finish_size_prefixed(root, None);
UniverseArgs { }
age: 0.0, } // pub mod goldens
galaxies: None, } // pub mod flatbuffers
}
}
}
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 * as flatbuffers from 'flatbuffers';
import { Galaxy } from './galaxy.js'; import { Galaxy } from '../../flatbuffers/goldens/galaxy.js';
export class Universe { export class Universe {
-16
View File
@@ -1,16 +0,0 @@
namespace models;
table HelloResponse {
message:string;
}
table HelloRequest {
name:string;
}
rpc_service Greeter {
Get(HelloRequest):HelloResponse;
Collect(HelloRequest):HelloResponse (streaming: "client");
Expand(HelloRequest):HelloResponse (streaming: "server");
Update(HelloRequest):HelloResponse (streaming: "bidi");
}
+25 -29
View File
@@ -1,4 +1,4 @@
// swift-tools-version:6.2 // swift-tools-version:5.10
/* /*
* Copyright 2020 Google Inc. All rights reserved. * Copyright 2020 Google Inc. All rights reserved.
* *
@@ -20,43 +20,39 @@ import PackageDescription
let package = Package( let package = Package(
name: "Greeter", name: "Greeter",
platforms: [ platforms: [
.iOS(.v18), .iOS(.v12),
.macOS(.v15), .macOS(.v10_14),
], ],
dependencies: [ dependencies: [
.package(path: "../../../.."), .package(path: "../../../../swift"),
.package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.0.0"), .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.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: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // 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. // Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target( .target(
name: "Models", name: "Model",
dependencies: [ dependencies: [
.product(name: "FlatBuffers", package: "flatbuffers"), "GRPC",
.product(name: "GRPCCore", package: "grpc-swift-2"), "FlatBuffers",
.product( ],
name: "GRPCNIOTransportHTTP2", path: "Sources/Model"),
package: "grpc-swift-nio-transport"),
]),
// Client for the Greeter example // Client for the Greeter example
.executableTarget( .target(
name: "Commands", name: "Client",
dependencies: [ dependencies: [
.product(name: "GRPCCore", package: "grpc-swift-2"), "GRPC",
.product( "Model",
name: "GRPCNIOTransportHTTP2", ],
package: "grpc-swift-nio-transport"), path: "Sources/client"),
.product(
name: "ArgumentParser", // Server for the Greeter example
package: "swift-argument-parser"), .target(
"Models", name: "Server",
]), dependencies: [
"GRPC",
"Model",
],
path: "Sources/server"),
]) ])
@@ -1,28 +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 ArgumentParser
let port = 3000
@main
struct GreeterCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "greeter",
abstract: "A multi-tool to run an echo server and execute RPCs against it.",
subcommands: [ServerCommand.self, ClientCommand.self])
}
@@ -1,121 +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 GRPCCore
import Models
struct GreeterService: models_Greeter.SimpleServiceProtocol {
func Get(
request: GRPCMessage<models_HelloResponse>,
context: GRPCCore
.ServerContext) async throws -> GRPCMessage<models_HelloResponse>
{
let model = try request.decode()
print("## GreeterService.Get: \(model.message)")
var builder = FlatBufferBuilder(initialSize: 128)
let off = builder.create(string: "Hello \(model.message ?? "Unknown")")
let root = models_HelloResponse.createHelloResponse(
&builder,
messageOffset: off)
builder.finish(offset: root)
return try GRPCMessage<models_HelloResponse>(builder: &builder)
}
func Collect(
request: GRPCCore.RPCAsyncSequence<
GRPCMessage<models_HelloResponse>,
any Swift.Error
>,
context: GRPCCore
.ServerContext) async throws -> GRPCMessage<models_HelloResponse>
{
let messages: [String] = try await request
.reduce(into: []) { array, message in
let model = try message.decode()
return array.append(model.message ?? "Unknown")
}
let joined = messages.joined(separator: ", ")
print("## GreeterService.Collect: \(joined)")
var builder = FlatBufferBuilder(initialSize: 128)
let off = builder.create(string: "Hello \(joined)")
let root = models_HelloResponse.createHelloResponse(
&builder,
messageOffset: off)
builder.finish(offset: root)
return try GRPCMessage<models_HelloResponse>(builder: &builder)
}
func Expand(
request: GRPCMessage<models_HelloResponse>,
response: GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext) async throws
{
let model = try request.decode()
print("## GreeterService.Expand: \(model.message)")
let message = model.message ?? "Unknown"
let stream = AsyncThrowingStream<
GRPCMessage<models_HelloResponse>,
Error
> { continuation in
var builder = FlatBufferBuilder(initialSize: 128)
for char in message {
let off = builder.create(string: "\(char)")
let root = models_HelloResponse.createHelloResponse(
&builder,
messageOffset: off)
builder.finish(offset: root)
do {
continuation
.yield(try GRPCMessage<models_HelloResponse>(builder: &builder))
} catch {
continuation.finish(throwing: error)
}
}
continuation.finish()
}
try await response.write(contentsOf: stream)
}
func Update(
request: GRPCCore.RPCAsyncSequence<
GRPCMessage<models_HelloResponse>,
any Swift.Error
>,
response: GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext) async throws
{
for try await message in request {
let model = try message.decode()
print("## GreeterService.Update: \(model.message)")
var builder = FlatBufferBuilder(initialSize: 128)
let off = builder.create(string: "Hello \(model.message ?? "Unknown")")
let root = models_HelloResponse.createHelloResponse(
&builder,
messageOffset: off)
builder.finish(offset: root)
try await response
.write(try GRPCMessage<models_HelloResponse>(builder: &builder))
}
}
}
@@ -1,140 +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 ArgumentParser
import FlatBuffers
import GRPCCore
import GRPCNIOTransportHTTP2
import Models
enum ClientRequest: String, ExpressibleByArgument {
case get, expand, collect, update
}
struct ClientCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "client")
@Option(help: "Name to send to the server")
var name: String
@Option(help: "request type")
var request: ClientRequest
func run() async throws {
try await withGRPCClient(
transport: .http2NIOPosix(
target: .dns(host: "localhost", port: port),
transportSecurity: .plaintext))
{
let client = models_Greeter.Client(wrapping: $0)
switch request {
case .get: try await get(client: client)
case .expand: try await expand(client: client)
case .collect: try await collect(client: client)
case .update: try await update(client: client)
}
}
}
func get(
client: models_Greeter
.Client<HTTP2ClientTransport.Posix>) async throws
{
for _ in 0..<3 {
var builder = FlatBufferBuilder(initialSize: 64)
let off = builder.create(string: name)
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: off)
builder.finish(offset: root)
let response = try await client
.Get(GRPCMessage(builder: &builder))
let message = try? response.decode().message
print("get message: \(message ?? "nil")")
}
}
func expand(
client: models_Greeter
.Client<HTTP2ClientTransport.Posix>) async throws
{
for _ in 0..<3 {
var builder = FlatBufferBuilder(initialSize: 64)
let off = builder.create(string: name)
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: off)
builder.finish(offset: root)
try await client.Expand(GRPCMessage(builder: &builder)) { response in
for try await message in response.messages {
let message = try? message.decode().message
print("expand message: \(message ?? "nil")")
}
}
}
}
func collect(
client: models_Greeter
.Client<HTTP2ClientTransport.Posix>) async throws
{
for _ in 0..<3 {
let response = try await client.Collect { writer in
for part in name {
print("collect sending: \(part)")
var builder = FlatBufferBuilder(initialSize: 64)
let off = builder.create(string: String(part))
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: off)
builder.finish(offset: root)
try await writer.write(GRPCMessage(builder: &builder))
}
}
let message = try response.decode().message
print("collect message: \(message ?? "nil")")
}
}
func update(
client: models_Greeter
.Client<HTTP2ClientTransport.Posix>) async throws
{
for _ in 0..<3 {
try await client.Update { writer in
for part in name {
print("update sending: \(part)")
var builder = FlatBufferBuilder(initialSize: 64)
let off = builder.create(string: String(part))
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: off)
builder.finish(offset: root)
try await writer.write(GRPCMessage(builder: &builder))
}
} onResponse: { response in
for try await message in response.messages {
let message = try message.decode().message
print("collect message: \(message ?? "nil")")
}
}
}
}
}
@@ -1,39 +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 ArgumentParser
import GRPCCore
import GRPCNIOTransportHTTP2
struct ServerCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "serve")
func run() async throws {
let server = GRPCServer(
transport: .http2NIOPosix(
address: .ipv4(host: "127.0.0.1", port: port),
transportSecurity: .plaintext),
services: [GreeterService()])
try await withThrowingDiscardingTaskGroup { group in
group.addTask { try await server.serve() }
if let address = try await server.listeningAddress {
print("Echo listening on \(address)")
}
}
}
}
@@ -0,0 +1,147 @@
// 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
@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct models_HelloResponse: FlatBufferVerifiableTable, FlatbuffersVectorInitializable { public struct models_HelloReply: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -17,43 +17,45 @@ public struct models_HelloResponse: FlatBufferVerifiableTable, FlatbuffersVector
private init(_ t: Table) { _accessor = t } private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private struct VT { private enum VTOFFSET: VOffset {
static let message: VOffset = 4 case message = 4
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
} }
public var message: String? { let o = _accessor.offset(VT.message); return o == 0 ? nil : _accessor.string(at: o) } 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: VT.message) } public var messageSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.message.v) }
public static func startHelloResponse(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) } 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: VT.message) } public static func add(message: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: message, at: VTOFFSET.message.p) }
public static func endHelloResponse(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } public static func endHelloReply(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createHelloResponse( public static func createHelloReply(
_ fbb: inout FlatBufferBuilder, _ fbb: inout FlatBufferBuilder,
messageOffset message: Offset = Offset() messageOffset message: Offset = Offset()
) -> Offset { ) -> Offset {
let __start = models_HelloResponse.startHelloResponse(&fbb) let __start = models_HelloReply.startHelloReply(&fbb)
models_HelloResponse.add(message: message, &fbb) models_HelloReply.add(message: message, &fbb)
return models_HelloResponse.endHelloResponse(&fbb, start: __start) 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 { 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) var _v = try verifier.visitTable(at: position)
try _v.visit(field: VT.message, fieldName: "message", required: false, type: ForwardOffset<String>.self) try _v.visit(field: VTOFFSET.message.p, fieldName: "message", required: false, type: ForwardOffset<String>.self)
_v.finish() _v.finish()
} }
} }
extension models_HelloResponse: Encodable { extension models_HelloReply: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case message = "message" case message = "message"
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(message, forKey: .message) try container.encodeIfPresent(message, forKey: .message)
} }
} }
public struct models_HelloRequest: FlatBufferVerifiableTable, FlatbuffersVectorInitializable { public struct models_HelloRequest: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -62,14 +64,16 @@ public struct models_HelloRequest: FlatBufferVerifiableTable, FlatbuffersVectorI
private init(_ t: Table) { _accessor = t } private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private struct VT { private enum VTOFFSET: VOffset {
static let name: VOffset = 4 case name = 4
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
} }
public var name: String? { let o = _accessor.offset(VT.name); return o == 0 ? nil : _accessor.string(at: 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: VT.name) } 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 startHelloRequest(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) }
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VT.name) } 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 endHelloRequest(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createHelloRequest( public static func createHelloRequest(
_ fbb: inout FlatBufferBuilder, _ fbb: inout FlatBufferBuilder,
@@ -82,16 +86,16 @@ public struct models_HelloRequest: FlatBufferVerifiableTable, FlatbuffersVectorI
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable { 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) var _v = try verifier.visitTable(at: position)
try _v.visit(field: VT.name, fieldName: "name", required: false, type: ForwardOffset<String>.self) try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
_v.finish() _v.finish()
} }
} }
extension models_HelloRequest: Encodable { extension models_HelloRequest: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case name = "name" case name = "name"
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(name, forKey: .name) try container.encodeIfPresent(name, forKey: .name)
@@ -1,572 +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) && compiler(>=6.0)
import FlatBuffers
import Foundation
import GRPCCore
import GRPCNIOTransportCore
/// Usage: instantiate models.GreeterServiceClient, then call methods of this protocol to make API calls.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension FlatBuffersMessageSerializer: MessageSerializer {
public func serialize<Bytes>(_ message: Message) throws -> Bytes where Bytes : GRPCCore.GRPCContiguousBytes {
do {
return try self.serialize(message: message) { GRPCNIOTransportBytes($0) } as! Bytes
} catch let error {
throw RPCError(
code: .invalidArgument,
message: "Can't serialize message",
cause: error
)
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension FlatBuffersMessageDeserializer: MessageDeserializer {
public func deserialize<Bytes>(_ serializedMessageBytes: Bytes) throws -> Message where Bytes : GRPCCore.GRPCContiguousBytes {
do {
return try serializedMessageBytes.withUnsafeBytes {
try self.deserialize(pointer: $0)
}
} catch let error {
throw RPCError(
code: .invalidArgument,
message: "Can't Decode message of type \(Message.self)",
cause: error
)
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public enum models_Greeter: Sendable {
public static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter")
public enum Method: Sendable {
public enum Get: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = models_HelloResponse
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter"),
method: "Get"
)
}
public enum Collect: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = models_HelloResponse
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter"),
method: "Collect"
)
}
public enum Expand: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = models_HelloResponse
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter"),
method: "Expand"
)
}
public enum Update: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = models_HelloResponse
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter"),
method: "Update"
)
}
public static let descriptors: [GRPCCore.MethodDescriptor] = [
Get.descriptor,
Collect.descriptor,
Expand.descriptor,
Update.descriptor,
]
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension GRPCCore.ServiceDescriptor {
public static let models_Greeter = GRPCCore.ServiceDescriptor(fullyQualifiedService: "models.Greeter")
}
// MARK: models.Greeter Server
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter {
public protocol StreamingServiceProtocol: GRPCCore.RegistrableRPCService {
func Get(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
func Collect(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
func Expand(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
func Update(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
}
public protocol ServiceProtocol: models_Greeter.StreamingServiceProtocol {
func Get(
request: GRPCCore.ServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>>
func Collect(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>>
func Expand(
request: GRPCCore.ServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
func Update(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>
}
public protocol SimpleServiceProtocol: models_Greeter.ServiceProtocol {
func Get(
request: GRPCMessage<models_HelloResponse>,
context: GRPCCore.ServerContext
) async throws -> GRPCMessage<models_HelloResponse>
func Collect(
request: GRPCCore.RPCAsyncSequence<GRPCMessage<models_HelloResponse>, any Swift.Error>,
context: GRPCCore.ServerContext
) async throws -> GRPCMessage<models_HelloResponse>
func Expand(
request: GRPCMessage<models_HelloResponse>,
response: GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws
func Update(
request: GRPCCore.RPCAsyncSequence<GRPCMessage<models_HelloResponse>, any Swift.Error>,
response: GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter.StreamingServiceProtocol {
public func registerMethods<Transport>(with router: inout GRPCCore.RPCRouter<Transport>) where Transport: GRPCCore.ServerTransport {
router.registerHandler(
forMethod: models_Greeter.Method.Get.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
handler: { request, context in
try await self.Get(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: models_Greeter.Method.Collect.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
handler: { request, context in
try await self.Collect(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: models_Greeter.Method.Expand.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
handler: { request, context in
try await self.Expand(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: models_Greeter.Method.Update.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
handler: { request, context in
try await self.Update(
request: request,
context: context
)
}
)
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter.ServiceProtocol {
public func Get(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>> {
let response = try await self.Get(
request: GRPCCore.ServerRequest(stream: request),
context: context
)
return GRPCCore.StreamingServerResponse(single: response)
}
public func Collect(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>> {
let response = try await self.Collect(
request: request,
context: context
)
return GRPCCore.StreamingServerResponse(single: response)
}
public func Expand(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>> {
let response = try await self.Expand(
request: GRPCCore.ServerRequest(stream: request),
context: context
)
return response
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter.SimpleServiceProtocol {
public func Get(
request: GRPCCore.ServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>> {
return GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>>(
message: try await self.Get(
request: request.message,
context: context
),
metadata: [:]
)
}
public func Collect(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>> {
return GRPCCore.ServerResponse<GRPCMessage<models_HelloResponse>>(
message: try await self.Collect(
request: request.messages,
context: context
),
metadata: [:]
)
}
public func Expand(
request: GRPCCore.ServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>> {
return GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>(
metadata: [:],
producer: { writer in
try await self.Expand(
request: request.message,
response: writer,
context: context
)
return [:]
}
)
}
public func Update(
request: GRPCCore.StreamingServerRequest<GRPCMessage<models_HelloResponse>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>> {
return GRPCCore.StreamingServerResponse<GRPCMessage<models_HelloResponse>>(
metadata: [:],
producer: { writer in
try await self.Update(
request: request.messages,
response: writer,
context: context
)
return [:]
}
)
}
}
// MARK: models.Greeter Client
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter {
public protocol ClientProtocol: Sendable {
func Get<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable
func Collect<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable
func Expand<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable
func Update<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter {
public struct Client<Transport>: ClientProtocol where Transport: GRPCCore.ClientTransport {
private let client: GRPCCore.GRPCClient<Transport>
public init(wrapping client: GRPCCore.GRPCClient<Transport>) {
self.client = client
}
public func Get<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.client.unary(
request: request,
descriptor: models_Greeter.Method.Get.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func Collect<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.client.clientStreaming(
request: request,
descriptor: models_Greeter.Method.Collect.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func Expand<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.client.serverStreaming(
request: request,
descriptor: models_Greeter.Method.Expand.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func Update<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<models_HelloResponse>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.client.bidirectionalStreaming(
request: request,
descriptor: models_Greeter.Method.Update.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter.ClientProtocol {
public func Get<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.Get(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
options: options,
onResponse: handleResponse
)
}
public func Collect<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.Collect(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
options: options,
onResponse: handleResponse
)
}
public func Expand<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.Expand(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
options: options,
onResponse: handleResponse
)
}
public func Update<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.Update(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<models_HelloResponse>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<models_HelloResponse>>(),
options: options,
onResponse: handleResponse
)
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension models_Greeter.ClientProtocol {
public func Get<Result>(
_ message: GRPCMessage<models_HelloResponse>,
metadata: GRPCCore.Metadata = [:],
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { try $0.message }
) async throws -> Result where Result: Sendable {
let request = GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>(
message: message,
metadata: metadata
)
return try await self.Get(
request: request,
options: options,
onResponse: handleResponse
)
}
public func Collect<Result>(
metadata: GRPCCore.Metadata = [:],
options: GRPCCore.CallOptions = .defaults,
requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>) async throws -> Void,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result = { try $0.message }
) async throws -> Result where Result: Sendable {
let request = GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>(
metadata: metadata,
producer: producer
)
return try await self.Collect(
request: request,
options: options,
onResponse: handleResponse
)
}
public func Expand<Result>(
_ message: GRPCMessage<models_HelloResponse>,
metadata: GRPCCore.Metadata = [:],
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
let request = GRPCCore.ClientRequest<GRPCMessage<models_HelloResponse>>(
message: message,
metadata: metadata
)
return try await self.Expand(
request: request,
options: options,
onResponse: handleResponse
)
}
public func Update<Result>(
metadata: GRPCCore.Metadata = [:],
options: GRPCCore.CallOptions = .defaults,
requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<GRPCMessage<models_HelloResponse>>) async throws -> Void,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<models_HelloResponse>>) async throws -> Result
) async throws -> Result where Result: Sendable {
let request = GRPCCore.StreamingClientRequest<GRPCMessage<models_HelloResponse>>(
metadata: metadata,
producer: producer
)
return try await self.Update(
request: request,
options: options,
onResponse: handleResponse
)
}
}
#endif
@@ -0,0 +1,108 @@
/*
* 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)
@@ -0,0 +1,97 @@
/*
* 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()
+5 -14
View File
@@ -172,7 +172,6 @@ class StubGenerator : public BaseGenerator {
<< " def __init__(self, channel: grpc.Channel) -> None: ...\n"; << " def __init__(self, channel: grpc.Channel) -> None: ...\n";
for (const RPCCall* method : service->calls.vec) { for (const RPCCall* method : service->calls.vec) {
imports->Import("typing");
std::string request = "bytes"; std::string request = "bytes";
std::string response = "bytes"; std::string response = "bytes";
@@ -184,22 +183,14 @@ class StubGenerator : public BaseGenerator {
imports->Import(ModuleFor(method->response), response); imports->Import(ModuleFor(method->response), response);
} }
ss << " def " << method->name << "(\n"; ss << " def " << method->name << "(self, ";
ss << " self,\n";
if (ClientStreaming(method)) { if (ClientStreaming(method)) {
ss << " request_iterator: typing.Iterator[" << request << "]\n"; imports->Import("typing");
ss << "request_iterator: typing.Iterator[" << request << "]";
} else { } else {
ss << " request: " << request << ",\n"; ss << "request: " << request;
} }
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)) { if (ServerStreaming(method)) {
imports->Import("typing"); imports->Import("typing");
ss << "typing.Iterator[" << response << "]"; ss << "typing.Iterator[" << response << "]";
File diff suppressed because it is too large Load Diff
+13
View File
@@ -142,6 +142,19 @@
#define FLATBUFFERS_VERSION_MAJOR 25 #define FLATBUFFERS_VERSION_MAJOR 25
#define FLATBUFFERS_VERSION_MINOR 12 #define FLATBUFFERS_VERSION_MINOR 12
#define FLATBUFFERS_VERSION_REVISION 19 #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_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers { namespace flatbuffers {
+4 -18
View File
@@ -1207,20 +1207,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
String(str); 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) { size_t Blob(const void* data, size_t len) {
return CreateBlob(data, len, 0, FBT_BLOB); return CreateBlob(data, len, 0, FBT_BLOB);
} }
size_t Blob(const std::vector<uint8_t>& v) { size_t Blob(const std::vector<uint8_t>& v) {
return Blob(v.data(), v.size()); return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
} }
void Blob(const char* key, const void* data, size_t len) { void Blob(const char* key, const void* data, size_t len) {
@@ -1702,16 +1693,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
size_t CreateBlob(const void* data, size_t len, size_t trailing, Type type) { size_t CreateBlob(const void* data, size_t len, size_t trailing, Type type) {
auto bit_width = WidthU(len); auto bit_width = WidthU(len);
return CreateAlignedBlob(data, len, trailing, type, bit_width); auto byte_width = Align(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); Write<uint64_t>(len, byte_width);
auto sloc = buf_.size(); auto sloc = buf_.size();
WriteBytes(data, len + trailing); WriteBytes(data, len + trailing);
stack_.push_back(Value(static_cast<uint64_t>(sloc), type, alignment)); stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
return sloc; return sloc;
} }
@@ -1976,7 +1962,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool VerifyKey(const uint8_t* p) { bool VerifyKey(const uint8_t* p) {
FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY)); FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
while (p < buf_ + size_) while (p < buf_ + size_)
if (!*p++) return true; if (*p++) return true;
return false; return false;
} }
+4
View File
@@ -677,6 +677,7 @@ struct IDLOptions {
std::string cpp_object_api_pointer_type; std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type; std::string cpp_object_api_string_type;
bool cpp_object_api_string_flexible_constructor; bool cpp_object_api_string_flexible_constructor;
std::string cpp_object_api_vector_type;
CaseStyle cpp_object_api_field_case_style; CaseStyle cpp_object_api_field_case_style;
bool cpp_direct_copy; bool cpp_direct_copy;
bool gen_nullable; bool gen_nullable;
@@ -1012,10 +1013,13 @@ class Parser : public ParserState {
known_attributes_["cpp_ptr_type_get"] = true; known_attributes_["cpp_ptr_type_get"] = true;
known_attributes_["cpp_str_type"] = true; known_attributes_["cpp_str_type"] = true;
known_attributes_["cpp_str_flex_ctor"] = true; known_attributes_["cpp_str_flex_ctor"] = true;
known_attributes_["cpp_vector_type"] = true;
known_attributes_["native_inline"] = true; known_attributes_["native_inline"] = true;
known_attributes_["native_custom_alloc"] = true; known_attributes_["native_custom_alloc"] = true;
known_attributes_["native_type"] = true; known_attributes_["native_type"] = true;
known_attributes_["native_type_pack_name"] = 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_["native_default"] = true;
known_attributes_["flexbuffer"] = true; known_attributes_["flexbuffer"] = true;
known_attributes_["private"] = true; known_attributes_["private"] = true;
+35 -37
View File
@@ -30,52 +30,50 @@ namespace flatbuffers {
// ------------------------- GETTERS ------------------------- // ------------------------- GETTERS -------------------------
constexpr bool IsScalar(reflection::BaseType t) { inline bool IsScalar(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::Double; return t >= reflection::UType && t <= reflection::Double;
} }
constexpr bool IsInteger(reflection::BaseType t) { inline bool IsInteger(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::ULong; return t >= reflection::UType && t <= reflection::ULong;
} }
constexpr bool IsFloat(reflection::BaseType t) { inline bool IsFloat(reflection::BaseType t) {
return t == reflection::Float || t == reflection::Double; return t == reflection::Float || t == reflection::Double;
} }
constexpr bool IsLong(reflection::BaseType t) { inline bool IsLong(reflection::BaseType t) {
return t == reflection::Long || t == reflection::ULong; return t == reflection::Long || t == reflection::ULong;
} }
// 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(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. // Size of a basic type, don't use with structs.
constexpr size_t GetTypeSize(reflection::BaseType base_type) { inline size_t GetTypeSize(reflection::BaseType base_type) {
return kBaseTypeSize[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
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];
} }
// Same as above, but now correctly returns the size of a struct if // Same as above, but now correctly returns the size of a struct if
@@ -422,7 +420,7 @@ pointer_inside_vector<T, U> piv(T* ptr, std::vector<U>& vec) {
return pointer_inside_vector<T, U>(ptr, vec); return pointer_inside_vector<T, U>(ptr, vec);
} }
constexpr const char* UnionTypeFieldSuffix() { return "_type"; } inline const char* UnionTypeFieldSuffix() { return "_type"; }
// Helper to figure out the actual table type a union refers to. // Helper to figure out the actual table type a union refers to.
inline const reflection::Object& GetUnionType( inline const reflection::Object& GetUnionType(
+2 -1
View File
@@ -438,7 +438,8 @@ namespace Google.FlatBuffers
if (off > Offset) if (off > Offset)
throw new ArgumentException(); throw new ArgumentException();
off = Offset - off + sizeof(int); if (off != 0)
off = Offset - off + sizeof(int);
PutInt(off); PutInt(off);
} }
+5 -1
View File
@@ -65,7 +65,11 @@ namespace Google.FlatBuffers
// Create a .NET String from UTF-8 data stored inside the flatbuffer. // Create a .NET String from UTF-8 data stored inside the flatbuffer.
public string __string(int offset) public string __string(int offset)
{ {
offset += bb.GetInt(offset); int stringOffset = bb.GetInt(offset);
if (stringOffset == 0)
return null;
offset += stringOffset;
var len = bb.GetInt(offset); var len = bb.GetInt(offset);
var startPos = offset + sizeof(int); var startPos = offset + sizeof(int);
return bb.GetStringUTF8(startPos, len); return bb.GetStringUTF8(startPos, len);
+19 -25
View File
@@ -33,12 +33,6 @@ importers:
specifier: ^8.34.1 specifier: ^8.34.1
version: 8.34.1(eslint@9.29.0)(typescript@5.8.3) version: 8.34.1(eslint@9.29.0)(typescript@5.8.3)
tests/ts:
dependencies:
flatbuffers:
specifier: workspace:*
version: link:../..
packages: packages:
'@esbuild/aix-ppc64@0.25.5': '@esbuild/aix-ppc64@0.25.5':
@@ -349,8 +343,8 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
ajv@6.14.0: ajv@6.12.6:
resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
ansi-styles@4.3.0: ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@@ -489,8 +483,8 @@ packages:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'} engines: {node: '>=16'}
flatted@3.4.2: flatted@3.3.1:
resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
glob-parent@5.1.2: glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@@ -577,11 +571,11 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
minimatch@3.1.5: minimatch@3.1.2:
resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@9.0.9: minimatch@9.0.5:
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
ms@2.1.3: ms@2.1.3:
@@ -799,7 +793,7 @@ snapshots:
dependencies: dependencies:
'@eslint/object-schema': 2.1.6 '@eslint/object-schema': 2.1.6
debug: 4.3.7 debug: 4.3.7
minimatch: 3.1.5 minimatch: 3.1.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -815,14 +809,14 @@ snapshots:
'@eslint/eslintrc@3.3.1': '@eslint/eslintrc@3.3.1':
dependencies: dependencies:
ajv: 6.14.0 ajv: 6.12.6
debug: 4.3.7 debug: 4.3.7
espree: 10.4.0 espree: 10.4.0
globals: 14.0.0 globals: 14.0.0
ignore: 5.3.2 ignore: 5.3.2
import-fresh: 3.3.0 import-fresh: 3.3.0
js-yaml: 4.1.1 js-yaml: 4.1.1
minimatch: 3.1.5 minimatch: 3.1.2
strip-json-comments: 3.1.1 strip-json-comments: 3.1.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -938,7 +932,7 @@ snapshots:
debug: 4.3.7 debug: 4.3.7
fast-glob: 3.3.2 fast-glob: 3.3.2
is-glob: 4.0.3 is-glob: 4.0.3
minimatch: 9.0.9 minimatch: 9.0.5
semver: 7.6.3 semver: 7.6.3
ts-api-utils: 2.1.0(typescript@5.8.3) ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3 typescript: 5.8.3
@@ -967,7 +961,7 @@ snapshots:
acorn@8.15.0: {} acorn@8.15.0: {}
ajv@6.14.0: ajv@6.12.6:
dependencies: dependencies:
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0 fast-json-stable-stringify: 2.1.0
@@ -1076,7 +1070,7 @@ snapshots:
'@humanwhocodes/retry': 0.4.3 '@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8 '@types/estree': 1.0.8
'@types/json-schema': 7.0.15 '@types/json-schema': 7.0.15
ajv: 6.14.0 ajv: 6.12.6
chalk: 4.1.2 chalk: 4.1.2
cross-spawn: 7.0.6 cross-spawn: 7.0.6
debug: 4.3.7 debug: 4.3.7
@@ -1095,7 +1089,7 @@ snapshots:
is-glob: 4.0.3 is-glob: 4.0.3
json-stable-stringify-without-jsonify: 1.0.1 json-stable-stringify-without-jsonify: 1.0.1
lodash.merge: 4.6.2 lodash.merge: 4.6.2
minimatch: 3.1.5 minimatch: 3.1.2
natural-compare: 1.4.0 natural-compare: 1.4.0
optionator: 0.9.4 optionator: 0.9.4
transitivePeerDependencies: transitivePeerDependencies:
@@ -1152,10 +1146,10 @@ snapshots:
flat-cache@4.0.1: flat-cache@4.0.1:
dependencies: dependencies:
flatted: 3.4.2 flatted: 3.3.1
keyv: 4.5.4 keyv: 4.5.4
flatted@3.4.2: {} flatted@3.3.1: {}
glob-parent@5.1.2: glob-parent@5.1.2:
dependencies: dependencies:
@@ -1224,11 +1218,11 @@ snapshots:
braces: 3.0.3 braces: 3.0.3
picomatch: 2.3.1 picomatch: 2.3.1
minimatch@3.1.5: minimatch@3.1.2:
dependencies: dependencies:
brace-expansion: 1.1.12 brace-expansion: 1.1.12
minimatch@9.0.9: minimatch@9.0.5:
dependencies: dependencies:
brace-expansion: 2.0.2 brace-expansion: 2.0.2
-2
View File
@@ -1,2 +0,0 @@
packages:
- tests/ts
+3 -3
View File
@@ -159,7 +159,7 @@ def EnumCreateValuesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateValuesVector(builder, data): def CreateValuesVector(builder, data):
return EnumCreateValuesVector(builder, data) EnumCreateValuesVector(builder, data)
def EnumAddIsUnion(builder, isUnion): def EnumAddIsUnion(builder, isUnion):
builder.PrependBoolSlot(2, isUnion, 0) builder.PrependBoolSlot(2, isUnion, 0)
@@ -189,7 +189,7 @@ def EnumCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return EnumCreateAttributesVector(builder, data) EnumCreateAttributesVector(builder, data)
def EnumAddDocumentation(builder, documentation): def EnumAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0) builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -207,7 +207,7 @@ def EnumCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return EnumCreateDocumentationVector(builder, data) EnumCreateDocumentationVector(builder, data)
def EnumAddDeclarationFile(builder, declarationFile): def EnumAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0) 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) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return EnumValCreateDocumentationVector(builder, data) EnumValCreateDocumentationVector(builder, data)
def EnumValAddAttributes(builder, attributes): def EnumValAddAttributes(builder, attributes):
builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0) builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
@@ -156,7 +156,7 @@ def EnumValCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return EnumValCreateAttributesVector(builder, data) EnumValCreateAttributesVector(builder, data)
def EnumValEnd(builder): def EnumValEnd(builder):
return builder.EndObject() return builder.EndObject()
+2 -2
View File
@@ -239,7 +239,7 @@ def FieldCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return FieldCreateAttributesVector(builder, data) FieldCreateAttributesVector(builder, data)
def FieldAddDocumentation(builder, documentation): def FieldAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(10, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0) builder.PrependUOffsetTRelativeSlot(10, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -257,7 +257,7 @@ def FieldCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return FieldCreateDocumentationVector(builder, data) FieldCreateDocumentationVector(builder, data)
def FieldAddOptional(builder, optional): def FieldAddOptional(builder, optional):
builder.PrependBoolSlot(11, optional, 0) builder.PrependBoolSlot(11, optional, 0)
+3 -3
View File
@@ -162,7 +162,7 @@ def ObjectCreateFieldsVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateFieldsVector(builder, data): def CreateFieldsVector(builder, data):
return ObjectCreateFieldsVector(builder, data) ObjectCreateFieldsVector(builder, data)
def ObjectAddIsStruct(builder, isStruct): def ObjectAddIsStruct(builder, isStruct):
builder.PrependBoolSlot(2, isStruct, 0) builder.PrependBoolSlot(2, isStruct, 0)
@@ -198,7 +198,7 @@ def ObjectCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return ObjectCreateAttributesVector(builder, data) ObjectCreateAttributesVector(builder, data)
def ObjectAddDocumentation(builder, documentation): def ObjectAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0) builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -216,7 +216,7 @@ def ObjectCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return ObjectCreateDocumentationVector(builder, data) ObjectCreateDocumentationVector(builder, data)
def ObjectAddDeclarationFile(builder, declarationFile): def ObjectAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(7, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0) 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) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return RPCCallCreateAttributesVector(builder, data) RPCCallCreateAttributesVector(builder, data)
def RPCCallAddDocumentation(builder, documentation): def RPCCallAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0) builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -160,7 +160,7 @@ def RPCCallCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return RPCCallCreateDocumentationVector(builder, data) RPCCallCreateDocumentationVector(builder, data)
def RPCCallEnd(builder): def RPCCallEnd(builder):
return builder.EndObject() return builder.EndObject()
+4 -4
View File
@@ -184,7 +184,7 @@ def SchemaCreateObjectsVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateObjectsVector(builder, data): def CreateObjectsVector(builder, data):
return SchemaCreateObjectsVector(builder, data) SchemaCreateObjectsVector(builder, data)
def SchemaAddEnums(builder, enums): def SchemaAddEnums(builder, enums):
builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(enums), 0) builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(enums), 0)
@@ -202,7 +202,7 @@ def SchemaCreateEnumsVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateEnumsVector(builder, data): def CreateEnumsVector(builder, data):
return SchemaCreateEnumsVector(builder, data) SchemaCreateEnumsVector(builder, data)
def SchemaAddFileIdent(builder, fileIdent): def SchemaAddFileIdent(builder, fileIdent):
builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(fileIdent), 0) builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(fileIdent), 0)
@@ -238,7 +238,7 @@ def SchemaCreateServicesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateServicesVector(builder, data): def CreateServicesVector(builder, data):
return SchemaCreateServicesVector(builder, data) SchemaCreateServicesVector(builder, data)
def SchemaAddAdvancedFeatures(builder, advancedFeatures): def SchemaAddAdvancedFeatures(builder, advancedFeatures):
builder.PrependUint64Slot(6, advancedFeatures, 0) builder.PrependUint64Slot(6, advancedFeatures, 0)
@@ -262,7 +262,7 @@ def SchemaCreateFbsFilesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateFbsFilesVector(builder, data): def CreateFbsFilesVector(builder, data):
return SchemaCreateFbsFilesVector(builder, data) SchemaCreateFbsFilesVector(builder, data)
def SchemaEnd(builder): def SchemaEnd(builder):
return builder.EndObject() return builder.EndObject()
+1 -1
View File
@@ -88,7 +88,7 @@ def SchemaFileCreateIncludedFilenamesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateIncludedFilenamesVector(builder, data): def CreateIncludedFilenamesVector(builder, data):
return SchemaFileCreateIncludedFilenamesVector(builder, data) SchemaFileCreateIncludedFilenamesVector(builder, data)
def SchemaFileEnd(builder): def SchemaFileEnd(builder):
return builder.EndObject() return builder.EndObject()
+3 -3
View File
@@ -141,7 +141,7 @@ def ServiceCreateCallsVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateCallsVector(builder, data): def CreateCallsVector(builder, data):
return ServiceCreateCallsVector(builder, data) ServiceCreateCallsVector(builder, data)
def ServiceAddAttributes(builder, attributes): def ServiceAddAttributes(builder, attributes):
builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0) builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(attributes), 0)
@@ -159,7 +159,7 @@ def ServiceCreateAttributesVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateAttributesVector(builder, data): def CreateAttributesVector(builder, data):
return ServiceCreateAttributesVector(builder, data) ServiceCreateAttributesVector(builder, data)
def ServiceAddDocumentation(builder, documentation): def ServiceAddDocumentation(builder, documentation):
builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0) builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(documentation), 0)
@@ -177,7 +177,7 @@ def ServiceCreateDocumentationVector(builder, data):
return builder.CreateVectorOfTables(data) return builder.CreateVectorOfTables(data)
def CreateDocumentationVector(builder, data): def CreateDocumentationVector(builder, data):
return ServiceCreateDocumentationVector(builder, data) ServiceCreateDocumentationVector(builder, data)
def ServiceAddDeclarationFile(builder, declarationFile): def ServiceAddDeclarationFile(builder, declarationFile):
builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0) builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(declarationFile), 0)
+5 -1
View File
@@ -1,2 +1,6 @@
[bdist_wheel]
universal=1
[metadata] [metadata]
license_files = LICENSE license_files =
../LICENSE
+30 -49
View File
@@ -12,54 +12,35 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from pathlib import Path
import shutil
from setuptools import setup from setuptools import setup
setup(
_THIS_DIR = Path(__file__).resolve().parent name='flatbuffers',
_ROOT_LICENSE = _THIS_DIR.parent / 'LICENSE' version='25.12.19',
_LOCAL_LICENSE = _THIS_DIR / 'LICENSE' license='Apache 2.0',
author='Derek Bailey',
author_email='derekbailey@google.com',
def _stage_license_file(): url='https://google.github.io/flatbuffers/',
if _LOCAL_LICENSE.exists() or not _ROOT_LICENSE.exists(): long_description=(
return False 'Python runtime library for use with the '
shutil.copyfile(_ROOT_LICENSE, _LOCAL_LICENSE) '`Flatbuffers <https://google.github.io/flatbuffers/>`_ '
return True 'serialization format.'
),
_remove_staged_license = _stage_license_file() packages=['flatbuffers'],
include_package_data=True,
try: requires=[],
setup( description='The FlatBuffers serialization format for Python',
name='flatbuffers', classifiers=[
version='25.12.19', 'Intended Audience :: Developers',
license='Apache 2.0', 'License :: OSI Approved :: Apache Software License',
author='Derek Bailey', 'Operating System :: OS Independent',
author_email='derekbailey@google.com', 'Programming Language :: Python',
url='https://google.github.io/flatbuffers/', 'Programming Language :: Python :: 2',
long_description=( 'Programming Language :: Python :: 3',
'Python runtime library for use with the ' 'Topic :: Software Development :: Libraries :: Python Modules',
'`Flatbuffers <https://google.github.io/flatbuffers/>`_ ' ],
'serialization format.' project_urls={
), 'Documentation': 'https://google.github.io/flatbuffers/',
packages=['flatbuffers'], 'Source': 'https://github.com/google/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()
+110 -579
View File
@@ -24,9 +24,6 @@ use core::marker::PhantomData;
use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, Sub, SubAssign}; use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, Sub, SubAssign};
use core::ptr::write_bytes; use core::ptr::write_bytes;
#[cfg(feature = "std")]
use std::collections::HashMap;
use crate::endian_scalar::emplace_scalar; use crate::endian_scalar::emplace_scalar;
use crate::primitives::*; use crate::primitives::*;
use crate::push::{Push, PushAlignment}; use crate::push::{Push, PushAlignment};
@@ -142,9 +139,6 @@ pub struct FlatBufferBuilder<'fbb, A: Allocator = DefaultAllocator> {
min_align: usize, min_align: usize,
force_defaults: bool, force_defaults: bool,
#[cfg(feature = "std")]
strings_pool: HashMap<String, WIPOffset<&'fbb str>>,
#[cfg(not(feature = "std"))]
strings_pool: Vec<WIPOffset<&'fbb str>>, strings_pool: Vec<WIPOffset<&'fbb str>>,
_phantom: PhantomData<&'fbb ()>, _phantom: PhantomData<&'fbb ()>,
@@ -166,60 +160,6 @@ impl<'fbb> FlatBufferBuilder<'fbb, DefaultAllocator> {
pub fn with_capacity(size: usize) -> Self { pub fn with_capacity(size: usize) -> Self {
Self::from_vec(vec![0; size]) 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 /// Create a FlatBufferBuilder that is ready for writing, reusing
/// an existing vector. /// an existing vector.
pub fn from_vec(buffer: Vec<u8>) -> Self { pub fn from_vec(buffer: Vec<u8>) -> Self {
@@ -257,52 +197,12 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
min_align: 0, min_align: 0,
force_defaults: false, force_defaults: false,
#[cfg(feature = "std")]
strings_pool: HashMap::new(),
#[cfg(not(feature = "std"))]
strings_pool: Vec::new(), strings_pool: Vec::new(),
_phantom: PhantomData, _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 /// Destroy the [`FlatBufferBuilder`], returning its [`Allocator`] and the index
/// into it that represents the start of valid data. /// into it that represents the start of valid data.
pub fn collapse_in(self) -> (A, usize) { pub fn collapse_in(self) -> (A, usize) {
@@ -323,9 +223,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// new object. /// new object.
pub fn reset(&mut self) { pub fn reset(&mut self) {
// memset only the part of the buffer that could be dirty: // memset only the part of the buffer that could be dirty:
self.allocator[self.head.range_to_end()] self.allocator[self.head.range_to_end()].iter_mut().for_each(|x| *x = 0);
.iter_mut()
.for_each(|x| *x = 0);
self.head = ReverseIndex::end(); self.head = ReverseIndex::end();
self.written_vtable_revpos.clear(); self.written_vtable_revpos.clear();
@@ -337,43 +235,22 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.strings_pool.clear(); self.strings_pool.clear();
} }
/// Fallible version of [`push`](Self::push).
#[inline]
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)?;
{
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()) };
}
Ok(WIPOffset::new(self.used_space() as UOffsetT))
}
/// Push a Push'able value onto the front of the in-progress data. /// Push a Push'able value onto the front of the in-progress data.
/// ///
/// This function uses traits to provide a unified API for writing /// This function uses traits to provide a unified API for writing
/// scalars, tables, vectors, and WIPOffsets. /// scalars, tables, vectors, and WIPOffsets.
#[inline] #[inline]
pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> { pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> {
self.try_push(x).expect("Flatbuffer allocation failure") let sz = P::size();
} self.align(sz, P::alignment());
self.make_space(sz);
/// Fallible version of [`push_slot`](Self::push_slot). {
#[inline] let (dst, rest) = self.allocator[self.head.range_to_end()].split_at_mut(sz);
pub fn try_push_slot<X: Push + PartialEq>( // Safety:
&mut self, // Called make_space above
slotoff: VOffsetT, unsafe { x.push(dst, rest.len()) };
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(()) WIPOffset::new(self.used_space() as UOffsetT)
} }
/// Push a Push'able value onto the front of the in-progress data, and /// Push a Push'able value onto the front of the in-progress data, and
@@ -381,29 +258,19 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// the default, then this is a no-op. /// the default, then this is a no-op.
#[inline] #[inline]
pub fn push_slot<X: Push + PartialEq>(&mut self, slotoff: VOffsetT, x: X, default: X) { pub fn push_slot<X: Push + PartialEq>(&mut self, slotoff: VOffsetT, x: X, default: X) {
self.try_push_slot(slotoff, x, default) self.assert_nested("push_slot");
.expect("Flatbuffer allocation failure") if x != default || self.force_defaults {
} self.push_slot_always(slotoff, x);
}
/// 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 /// Push a Push'able value onto the front of the in-progress data, and
/// store a reference to it in the in-progress vtable. /// store a reference to it in the in-progress vtable.
#[inline] #[inline]
pub fn push_slot_always<X: Push>(&mut self, slotoff: VOffsetT, x: X) { pub fn push_slot_always<X: Push>(&mut self, slotoff: VOffsetT, x: X) {
self.try_push_slot_always(slotoff, x) self.assert_nested("push_slot_always");
.expect("Flatbuffer allocation failure") let off = self.push(x);
self.track_field(slotoff, off.value());
} }
/// Retrieve the number of vtables that have been serialized into the /// Retrieve the number of vtables that have been serialized into the
@@ -428,22 +295,6 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
WIPOffset::new(self.used_space() as UOffsetT) 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. /// End a Table write.
/// ///
/// Asserts that the builder is in a nested state. /// Asserts that the builder is in a nested state.
@@ -452,19 +303,14 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
&mut self, &mut self,
off: WIPOffset<TableUnfinishedWIPOffset>, off: WIPOffset<TableUnfinishedWIPOffset>,
) -> WIPOffset<TableFinishedWIPOffset> { ) -> WIPOffset<TableFinishedWIPOffset> {
self.try_end_table(off) self.assert_nested("end_table");
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`start_vector`](Self::start_vector). let o = self.write_vtable(off);
#[inline]
pub fn try_start_vector<T: Push>(&mut self, num_items: usize) -> Result<(), A::Error> { self.nested = false;
self.assert_not_nested( self.field_locs.clear();
"start_vector can not be called when a table or vector is under construction",
); WIPOffset::new(o.value())
self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET))?;
self.nested = true;
Ok(())
} }
/// Start a Vector write. /// Start a Vector write.
@@ -476,20 +322,11 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// function will want to use `push` to add values. /// function will want to use `push` to add values.
#[inline] #[inline]
pub fn start_vector<T: Push>(&mut self, num_items: usize) { pub fn start_vector<T: Push>(&mut self, num_items: usize) {
self.try_start_vector::<T>(num_items) self.assert_not_nested(
.expect("Flatbuffer allocation failure") "start_vector can not be called when a table or vector is under construction",
} );
self.nested = true;
/// Fallible version of [`end_vector`](Self::end_vector). self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET));
#[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. /// End a Vector write.
@@ -500,54 +337,14 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// Asserts that the builder is in a nested state. /// Asserts that the builder is in a nested state.
#[inline] #[inline]
pub fn end_vector<T: Push>(&mut self, num_elems: usize) -> WIPOffset<Vector<'fbb, T>> { pub fn end_vector<T: Push>(&mut self, num_elems: usize) -> WIPOffset<Vector<'fbb, T>> {
self.try_end_vector::<T>(num_elems) self.assert_nested("end_vector");
.expect("Flatbuffer allocation failure") self.nested = false;
let o = self.push::<UOffsetT>(num_elems as UOffsetT);
WIPOffset::new(o.value())
} }
/// 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] #[inline]
pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> { 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( self.assert_not_nested(
"create_shared_string can not be called when a table or vector is under construction", "create_shared_string can not be called when a table or vector is under construction",
); );
@@ -558,95 +355,68 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
let found = self.strings_pool.binary_search_by(|offset| { let found = self.strings_pool.binary_search_by(|offset| {
let ptr = offset.value() as usize; let ptr = offset.value() as usize;
// Gets The pointer to the size of the string
let str_memory = &buf[buf.len() - ptr..]; let str_memory = &buf[buf.len() - ptr..];
let size = u32::from_le_bytes([ // Gets the size of the written string from buffer
str_memory[0], let size =
str_memory[1], u32::from_le_bytes([str_memory[0], str_memory[1], str_memory[2], str_memory[3]])
str_memory[2], as usize;
str_memory[3], // Size of the string size
]) as usize; let string_size: usize = 4;
let stored = &str_memory[4..4 + size]; // Fetches actual string bytes from index of string after string size
stored.cmp(s.as_bytes()) // 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())
}); });
match found { match found {
Ok(index) => Ok(self.strings_pool[index]), Ok(index) => self.strings_pool[index],
Err(index) => { Err(index) => {
let address = let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value());
WIPOffset::new(self.try_create_byte_string(s.as_bytes())?.value());
self.strings_pool.insert(index, address); self.strings_pool.insert(index, address);
Ok(address) 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. /// Create a utf8 string.
/// ///
/// The wire format represents this as a zero-terminated byte vector. /// The wire format represents this as a zero-terminated byte vector.
#[inline] #[inline]
pub fn create_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> { 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( self.assert_not_nested(
"create_byte_string can not be called when a table or vector is under construction", "create_string can not be called when a table or vector is under construction",
); );
self.align(data.len() + 1, PushAlignment::new(SIZE_UOFFSET))?; WIPOffset::new(self.create_byte_string(s.as_bytes()).value())
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. /// Create a zero-terminated byte vector.
#[inline] #[inline]
pub fn create_byte_string(&mut self, data: &[u8]) -> WIPOffset<&'fbb [u8]> { pub fn create_byte_string(&mut self, data: &[u8]) -> WIPOffset<&'fbb [u8]> {
self.try_create_byte_string(data) self.assert_not_nested(
.expect("Flatbuffer allocation failure") "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)
} }
/// Fallible version of [`create_vector`](Self::create_vector). /// 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] #[inline]
pub fn try_create_vector<'a: 'b, 'b, T: Push + 'b>( pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
&'a mut self, &'a mut self,
items: &'b [T], items: &'b [T],
) -> Result<WIPOffset<Vector<'fbb, T::Output>>, A::Error> { ) -> WIPOffset<Vector<'fbb, T::Output>> {
let elem_size = T::size(); let elem_size = T::size();
let slice_size = items.len() * elem_size; let slice_size = items.len() * elem_size;
self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET))?; self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET));
self.ensure_capacity(slice_size + UOffsetT::size())?; self.ensure_capacity(slice_size + UOffsetT::size());
self.head -= slice_size; self.head -= slice_size;
let mut written_len = self.head.distance_to_end(); let mut written_len = self.head.distance_to_end();
@@ -660,38 +430,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
unsafe { item.push(out, written_len) }; unsafe { item.push(out, written_len) };
} }
Ok(WIPOffset::new( WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
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. /// Create a vector of Push-able objects.
@@ -703,8 +442,14 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
&mut self, &mut self,
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator, items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
) -> WIPOffset<Vector<'fbb, T::Output>> { ) -> WIPOffset<Vector<'fbb, T::Output>> {
self.try_create_vector_from_iter(items) let elem_size = T::size();
.expect("Flatbuffer allocation failure") 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())
} }
/// Set whether default values are stored. /// Set whether default values are stored.
@@ -767,34 +512,13 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
assert!(o != 0, "missing required field {}", assert_msg_name); 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 /// Finalize the FlatBuffer by: aligning it, pushing an optional file
/// identifier on to it, pushing a size prefix on to it, and marking the /// identifier on to it, pushing a size prefix on to it, and marking the
/// internal state of the FlatBufferBuilder as `finished`. Afterwards, /// internal state of the FlatBufferBuilder as `finished`. Afterwards,
/// users can call `finished_data` to get the resulting data. /// users can call `finished_data` to get the resulting data.
#[inline] #[inline]
pub fn finish_size_prefixed<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) { pub fn finish_size_prefixed<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
self.try_finish_size_prefixed(root, file_identifier) self.finish_with_opts(root, file_identifier, true);
.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 /// Finalize the FlatBuffer by: aligning it, pushing an optional file
@@ -803,14 +527,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// `finished_data` to get the resulting data. /// `finished_data` to get the resulting data.
#[inline] #[inline]
pub fn finish<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) { pub fn finish<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
self.try_finish(root, file_identifier) self.finish_with_opts(root, file_identifier, false);
.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 /// Finalize the FlatBuffer by: aligning it and marking the internal state
@@ -818,8 +535,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
/// `finished_data` to get the resulting data. /// `finished_data` to get the resulting data.
#[inline] #[inline]
pub fn finish_minimal<T>(&mut self, root: WIPOffset<T>) { pub fn finish_minimal<T>(&mut self, root: WIPOffset<T>) {
self.try_finish_minimal(root) self.finish_with_opts(root, None, false);
.expect("Flatbuffer allocation failure")
} }
#[inline] #[inline]
@@ -837,13 +553,13 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
fn write_vtable( fn write_vtable(
&mut self, &mut self,
table_tail_revloc: WIPOffset<TableUnfinishedWIPOffset>, table_tail_revloc: WIPOffset<TableUnfinishedWIPOffset>,
) -> Result<WIPOffset<VTableWIPOffset>, A::Error> { ) -> WIPOffset<VTableWIPOffset> {
self.assert_nested("write_vtable"); self.assert_nested("write_vtable");
// Write the vtable offset, which is the start of any Table. // Write the vtable offset, which is the start of any Table.
// We fill its value later. // We fill its value later.
let object_revloc_to_vtable: WIPOffset<VTableWIPOffset> = let object_revloc_to_vtable: WIPOffset<VTableWIPOffset> =
WIPOffset::new(self.try_push::<UOffsetT>(0xF0F0_F0F0)?.value()); WIPOffset::new(self.push::<UOffsetT>(0xF0F0_F0F0).value());
// Layout of the data this function will create when a new vtable is // Layout of the data this function will create when a new vtable is
// needed. // needed.
@@ -886,7 +602,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
// fill the WIP vtable with zeros: // fill the WIP vtable with zeros:
let vtable_byte_len = get_vtable_byte_len(&self.field_locs); 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: // compute the length of the table (not vtable!) in bytes:
let table_object_size = object_revloc_to_vtable.value() - table_tail_revloc.value(); let table_object_size = object_revloc_to_vtable.value() - table_tail_revloc.value();
@@ -911,15 +627,13 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
} }
} }
let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)]; let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)];
let found = self let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| {
.written_vtable_revpos let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize;
.binary_search_by(|old_vtable_revpos: &UOffsetT| { // Safety:
let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize; // Already written vtables are valid by construction
// Safety: let old_vtable = unsafe { VTable::init(&self.allocator, old_vtable_pos) };
// Already written vtables are valid by construction new_vt_bytes.cmp(old_vtable.as_bytes())
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 { let final_vtable_revpos = match found {
Ok(i) => { Ok(i) => {
// The new vtable is a duplicate so clear it. // The new vtable is a duplicate so clear it.
@@ -957,18 +671,17 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.field_locs.clear(); self.field_locs.clear();
Ok(object_revloc_to_vtable) object_revloc_to_vtable
} }
// Only call this when you know it is safe to double the size of the buffer. // Only call this when you know it is safe to double the size of the buffer.
#[inline] #[inline]
fn grow_allocator(&mut self) -> Result<(), A::Error> { fn grow_allocator(&mut self) {
let starting_active_size = self.used_space(); let starting_active_size = self.used_space();
self.allocator.grow_downwards()?; self.allocator.grow_downwards().expect("Flatbuffer allocation failure");
let ending_active_size = self.used_space(); let ending_active_size = self.used_space();
debug_assert_eq!(starting_active_size, ending_active_size); debug_assert_eq!(starting_active_size, ending_active_size);
Ok(())
} }
// with or without a size prefix changes how we load the data, so finish* // with or without a size prefix changes how we load the data, so finish*
@@ -978,7 +691,7 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
root: WIPOffset<T>, root: WIPOffset<T>,
file_identifier: Option<&str>, file_identifier: Option<&str>,
size_prefixed: bool, size_prefixed: bool,
) -> Result<(), A::Error> { ) {
self.assert_not_finished("buffer cannot be finished when it is already finished"); self.assert_not_finished("buffer cannot be finished when it is already finished");
self.assert_not_nested( self.assert_not_nested(
"buffer cannot be finished when a table or vector is under construction", "buffer cannot be finished when a table or vector is under construction",
@@ -991,40 +704,34 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
// for the size prefix: // for the size prefix:
let b = if size_prefixed { SIZE_UOFFSET } else { 0 }; let b = if size_prefixed { SIZE_UOFFSET } else { 0 };
// for the file identifier (a string that is not zero-terminated): // for the file identifier (a string that is not zero-terminated):
let c = if file_identifier.is_some() { let c = if file_identifier.is_some() { FILE_IDENTIFIER_LENGTH } else { 0 };
FILE_IDENTIFIER_LENGTH
} else {
0
};
a + b + c a + b + c
}; };
{ {
let ma = PushAlignment::new(self.min_align); let ma = PushAlignment::new(self.min_align);
self.align(to_align, ma)?; self.align(to_align, ma);
} }
if let Some(ident) = file_identifier { if let Some(ident) = file_identifier {
debug_assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH); debug_assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
self.push_bytes_unprefixed(ident.as_bytes())?; self.push_bytes_unprefixed(ident.as_bytes());
} }
self.try_push(root)?; self.push(root);
if size_prefixed { if size_prefixed {
let sz = self.used_space() as UOffsetT; let sz = self.used_space() as UOffsetT;
self.try_push::<UOffsetT>(sz)?; self.push::<UOffsetT>(sz);
} }
self.finished = true; self.finished = true;
Ok(())
} }
#[inline] #[inline]
fn align(&mut self, len: usize, alignment: PushAlignment) -> Result<(), A::Error> { fn align(&mut self, len: usize, alignment: PushAlignment) {
self.track_min_align(alignment.value()); self.track_min_align(alignment.value());
let s = self.used_space() as usize; 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] #[inline]
@@ -1033,34 +740,31 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
} }
#[inline] #[inline]
fn push_bytes_unprefixed(&mut self, x: &[u8]) -> Result<UOffsetT, A::Error> { fn push_bytes_unprefixed(&mut self, x: &[u8]) -> UOffsetT {
let n = self.make_space(x.len())?; let n = self.make_space(x.len());
self.allocator[n.range_to(n + x.len())].copy_from_slice(x); self.allocator[n.range_to(n + x.len())].copy_from_slice(x);
Ok(n.to_forward_index(&self.allocator) as UOffsetT) n.to_forward_index(&self.allocator) as UOffsetT
} }
#[inline] #[inline]
fn make_space(&mut self, want: usize) -> Result<ReverseIndex, A::Error> { fn make_space(&mut self, want: usize) -> ReverseIndex {
self.ensure_capacity(want)?; self.ensure_capacity(want);
self.head -= want; self.head -= want;
Ok(self.head) self.head
} }
#[inline] #[inline]
fn ensure_capacity(&mut self, want: usize) -> Result<usize, A::Error> { fn ensure_capacity(&mut self, want: usize) -> usize {
if self.unused_ready_space() >= want { if self.unused_ready_space() >= want {
return Ok(want); return want;
} }
assert!( assert!(want <= FLATBUFFERS_MAX_BUFFER_SIZE, "cannot grow buffer beyond 2 gigabytes");
want <= FLATBUFFERS_MAX_BUFFER_SIZE,
"cannot grow buffer beyond 2 gigabytes"
);
while self.unused_ready_space() < want { while self.unused_ready_space() < want {
self.grow_allocator()?; self.grow_allocator();
} }
Ok(want) want
} }
#[inline] #[inline]
fn unused_ready_space(&self) -> usize { fn unused_ready_space(&self) -> usize {
@@ -1227,33 +931,6 @@ impl<T> IndexMut<ReverseIndexRange> for [T] {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; 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] #[test]
fn reverse_index_test() { fn reverse_index_test() {
@@ -1263,150 +940,4 @@ mod tests {
assert_eq!(&buf[idx.range_to(idx + 1)], &[4]); assert_eq!(&buf[idx.range_to(idx + 1)], &[4]);
assert_eq!(idx.to_forward_index(&buf), 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");
}
} }
+1 -15
View File
@@ -107,20 +107,6 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
key: K, key: K,
f: fn(&<T as Follow<'a>>::Inner, &K) -> Ordering, f: fn(&<T as Follow<'a>>::Inner, &K) -> Ordering,
) -> Option<T::Inner> { ) -> 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() { if self.is_empty() {
return None; return None;
} }
@@ -132,7 +118,7 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
let mid = (left + right) / 2; let mid = (left + right) / 2;
let value = self.get(mid); let value = self.get(mid);
match f(&value, &key) { match f(&value, &key) {
Ordering::Equal => return Some(mid), Ordering::Equal => return Some(value),
Ordering::Less => left = mid + 1, Ordering::Less => left = mid + 1,
Ordering::Greater => { Ordering::Greater => {
if mid == 0 { if mid == 0 {
+1 -1
View File
@@ -492,8 +492,8 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
Ok(self) Ok(self)
} }
_ => InvalidFlatbuffer::new_inconsistent_union( _ => InvalidFlatbuffer::new_inconsistent_union(
val_field_name.into(),
key_field_name.into(), key_field_name.into(),
val_field_name.into(),
), ),
} }
} }
+1 -1
View File
@@ -397,8 +397,8 @@ fn verify_union<'a, 'b, 'c>(
} }
} else { } else {
return InvalidFlatbuffer::new_inconsistent_union( return InvalidFlatbuffer::new_inconsistent_union(
field.name().to_string(),
format!("{}_type", field.name()), format!("{}_type", field.name()),
field.name().to_string(),
)?; )?;
} }
+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 _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0; auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0;
auto _color = _o->color; 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 MyGame::Sample::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 CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0;
auto _equipped_type = _o->equipped.type; auto _equipped_type = _o->equipped.type;
auto _equipped = _o->equipped.Pack(_fbb); auto _equipped = _o->equipped.Pack(_fbb);
auto _path = _o->path.size() ? _fbb.CreateVectorOfStructs(_o->path) : 0; auto _path = _o->path.size() ? _fbb.CreateVectorOfStructs(_o->path) : 0;
+69 -65
View File
@@ -113,12 +113,12 @@ public struct MyGame_Sample_Vec3: NativeStruct, FlatbuffersVectorInitializable,
} }
extension MyGame_Sample_Vec3: Encodable { extension MyGame_Sample_Vec3: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case x = "x" case x = "x"
case y = "y" case y = "y"
case z = "z" case z = "z"
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
if x != 0.0 { if x != 0.0 {
@@ -161,7 +161,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferStruct, FlatbuffersVectorIni
} }
} }
public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -170,49 +170,51 @@ public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVecto
private init(_ t: Table) { _accessor = t } private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private struct VT { private enum VTOFFSET: VOffset {
static let pos: VOffset = 4 case pos = 4
static let mana: VOffset = 6 case mana = 6
static let hp: VOffset = 8 case hp = 8
static let name: VOffset = 10 case name = 10
static let inventory: VOffset = 14 case inventory = 14
static let color: VOffset = 16 case color = 16
static let weapons: VOffset = 18 case weapons = 18
static let equippedType: VOffset = 20 case equippedType = 20
static let equipped: VOffset = 22 case equipped = 22
static let path: VOffset = 24 case path = 24
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
} }
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 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(VT.pos); return o == 0 ? nil : MyGame_Sample_Vec3_Mutable(_accessor.bb, o: o + _accessor.position) } 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(VT.mana); return o == 0 ? 150 : _accessor.readBuffer(of: Int16.self, at: o) } 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(VT.mana); return _accessor.mutate(mana, index: 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(VT.hp); return o == 0 ? 100 : _accessor.readBuffer(of: Int16.self, at: 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(VT.hp); return _accessor.mutate(hp, index: 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(VT.name); return o == 0 ? nil : _accessor.string(at: 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: VT.name) } public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
public var inventory: FlatbufferVector<UInt8> { return _accessor.vector(at: VT.inventory, byteSize: 1) } 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(VT.inventory); return _accessor.directMutate(inventory, index: _accessor.vector(at: o) + index * 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: VT.inventory, body: body) } 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(VT.color); return o == 0 ? .blue : MyGame_Sample_Color(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .blue } 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(VT.color); return _accessor.mutate(color.rawValue, index: o) } @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: VT.weapons, byteSize: 4) } 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(VT.equippedType); return o == 0 ? .none_ : MyGame_Sample_Equipment(rawValue: _accessor.readBuffer(of: UInt8.self, at: o)) ?? .none_ } 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(VT.equipped); return o == 0 ? nil : _accessor.union(o) } 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: VT.path, byteSize: 12) } 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: VT.path, 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: VT.path, body: body) } public func withUnsafePointerToPath<T>(_ body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return try _accessor.withUnsafePointerToSlice(at: VTOFFSET.path.v, body: body) }
public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 11) } 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: VT.pos) } 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: VT.mana) } 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: VT.hp) } 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: VT.name) } 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: VT.inventory) } 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: VT.color) } 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: VT.weapons) } 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: VT.equippedType) } 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: VT.equipped) } 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: VT.path) } public static func addVectorOf(path: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: path, at: VTOFFSET.path.p) }
public static func startVectorOfPath(_ size: Int, in builder: inout FlatBufferBuilder) { public static func startVectorOfPath(_ size: Int, in builder: inout FlatBufferBuilder) {
builder.startVector(size * MemoryLayout<MyGame_Sample_Vec3>.size, elementSize: MemoryLayout<MyGame_Sample_Vec3>.alignment) builder.startVector(size * MemoryLayout<MyGame_Sample_Vec3>.size, elementSize: MemoryLayout<MyGame_Sample_Vec3>.alignment)
} }
@@ -291,14 +293,14 @@ public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVecto
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable { 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) var _v = try verifier.visitTable(at: position)
try _v.visit(field: VT.pos, fieldName: "pos", required: false, type: MyGame_Sample_Vec3.self) try _v.visit(field: VTOFFSET.pos.p, 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: VTOFFSET.mana.p, fieldName: "mana", required: false, type: Int16.self)
try _v.visit(field: VT.hp, fieldName: "hp", required: false, type: Int16.self) try _v.visit(field: VTOFFSET.hp.p, 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: VTOFFSET.name.p, 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: VTOFFSET.inventory.p, 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: VTOFFSET.color.p, 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(field: VTOFFSET.weapons.p, 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 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
switch key { switch key {
case .none_: case .none_:
break // NOTE - SWIFT doesnt support none break // NOTE - SWIFT doesnt support none
@@ -306,12 +308,13 @@ public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVecto
try ForwardOffset<MyGame_Sample_Weapon>.verify(&verifier, at: pos, of: MyGame_Sample_Weapon.self) try ForwardOffset<MyGame_Sample_Weapon>.verify(&verifier, at: pos, of: MyGame_Sample_Weapon.self)
} }
}) })
try _v.visit(field: VT.path, fieldName: "path", required: false, type: ForwardOffset<Vector<MyGame_Sample_Vec3, MyGame_Sample_Vec3>>.self) try _v.visit(field: VTOFFSET.path.p, fieldName: "path", required: false, type: ForwardOffset<Vector<MyGame_Sample_Vec3, MyGame_Sample_Vec3>>.self)
_v.finish() _v.finish()
} }
} }
extension MyGame_Sample_Monster: Encodable { extension MyGame_Sample_Monster: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case pos = "pos" case pos = "pos"
case mana = "mana" case mana = "mana"
@@ -324,7 +327,6 @@ extension MyGame_Sample_Monster: Encodable {
case equipped = "equipped" case equipped = "equipped"
case path = "path" case path = "path"
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(pos, forKey: .pos) try container.encodeIfPresent(pos, forKey: .pos)
@@ -400,7 +402,7 @@ public class MyGame_Sample_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Sample_Monster.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Sample_Monster.self) }
} }
public struct MyGame_Sample_Weapon: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Sample_Weapon: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
public var __buffer: ByteBuffer! { return _accessor.bb } public var __buffer: ByteBuffer! { return _accessor.bb }
@@ -409,18 +411,20 @@ public struct MyGame_Sample_Weapon: FlatBufferVerifiableTable, FlatbuffersVector
private init(_ t: Table) { _accessor = t } private init(_ t: Table) { _accessor = t }
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
private struct VT { private enum VTOFFSET: VOffset {
static let name: VOffset = 4 case name = 4
static let damage: VOffset = 6 case damage = 6
var v: Int32 { Int32(self.rawValue) }
var p: VOffset { self.rawValue }
} }
public var name: String? { let o = _accessor.offset(VT.name); return o == 0 ? nil : _accessor.string(at: 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: VT.name) } public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
public var damage: Int16 { let o = _accessor.offset(VT.damage); return o == 0 ? 0 : _accessor.readBuffer(of: Int16.self, at: o) } 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(VT.damage); return _accessor.mutate(damage, index: o) } @discardableResult public func mutate(damage: Int16) -> Bool {let o = _accessor.offset(VTOFFSET.damage.v); return _accessor.mutate(damage, index: o) }
public static func startWeapon(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 2) } 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: VT.name) } 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: VT.damage) } public static func add(damage: Int16, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damage, def: 0, at: VTOFFSET.damage.p) }
public static func endWeapon(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } public static func endWeapon(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createWeapon( public static func createWeapon(
_ fbb: inout FlatBufferBuilder, _ fbb: inout FlatBufferBuilder,
@@ -457,18 +461,18 @@ public struct MyGame_Sample_Weapon: FlatBufferVerifiableTable, FlatbuffersVector
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable { 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) var _v = try verifier.visitTable(at: position)
try _v.visit(field: VT.name, fieldName: "name", required: false, type: ForwardOffset<String>.self) try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
try _v.visit(field: VT.damage, fieldName: "damage", required: false, type: Int16.self) try _v.visit(field: VTOFFSET.damage.p, fieldName: "damage", required: false, type: Int16.self)
_v.finish() _v.finish()
} }
} }
extension MyGame_Sample_Weapon: Encodable { extension MyGame_Sample_Weapon: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case name = "name" case name = "name"
case damage = "damage" case damage = "damage"
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(name, forKey: .name) try container.encodeIfPresent(name, forKey: .name)
+13 -13
View File
@@ -1,18 +1,18 @@
// Automatically generated by the Flatbuffers compiler. Do not modify. // Automatically generated by the Flatbuffers compiler. Do not modify.
// @generated // @generated
pub mod my_game { pub mod my_game {
use super::*;
pub mod sample {
use super::*; use super::*;
pub mod sample { mod color_generated;
use super::*; pub use self::color_generated::*;
mod color_generated; mod equipment_generated;
pub use self::color_generated::*; pub use self::equipment_generated::*;
mod equipment_generated; mod vec_3_generated;
pub use self::equipment_generated::*; pub use self::vec_3_generated::*;
mod vec_3_generated; mod monster_generated;
pub use self::vec_3_generated::*; pub use self::monster_generated::*;
mod monster_generated; mod weapon_generated;
pub use self::monster_generated::*; pub use self::weapon_generated::*;
mod weapon_generated; } // sample
pub use self::weapon_generated::*;
} // sample
} // my_game } // my_game
@@ -2,73 +2,64 @@
// @generated // @generated
extern crate alloc; extern crate alloc;
use super::*; use super::*;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] #[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; 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.")] #[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; 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.")] #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub const ENUM_VALUES_COLOR: [Color; 3] = [ pub const ENUM_VALUES_COLOR: [Color; 3] = [
Color::Red, Color::Red,
Color::Green, Color::Green,
Color::Blue, Color::Blue,
]; ];
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)] #[repr(transparent)]
pub struct Color(pub i8); pub struct Color(pub i8);
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
impl Color { impl Color {
pub const Red: Self = Self(0); pub const Red: Self = Self(0);
pub const Green: Self = Self(1); pub const Green: Self = Self(1);
pub const Blue: Self = Self(2); pub const Blue: Self = Self(2);
pub const ENUM_MIN: i8 = 0; pub const ENUM_MIN: i8 = 0;
pub const ENUM_MAX: i8 = 2; pub const ENUM_MAX: i8 = 2;
pub const ENUM_VALUES: &'static [Self] = &[ pub const ENUM_VALUES: &'static [Self] = &[
Self::Red, Self::Red,
Self::Green, Self::Green,
Self::Blue, Self::Blue,
]; ];
/// Returns the variant's name or "" if unknown.
/// Returns the variant's name or "" if unknown. pub fn variant_name(self) -> Option<&'static str> {
pub fn variant_name(self) -> Option<&'static str> { match self {
match self { Self::Red => Some("Red"),
Self::Red => Some("Red"), Self::Green => Some("Green"),
Self::Green => Some("Green"), Self::Blue => Some("Blue"),
Self::Blue => Some("Blue"), _ => None,
_ => None,
}
} }
}
} }
impl ::core::fmt::Debug for Color { impl ::core::fmt::Debug for Color {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() { if let Some(name) = self.variant_name() {
f.write_str(name) f.write_str(name)
} else { } else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0)) f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
}
} }
}
} }
impl<'a> ::flatbuffers::Follow<'a> for Color { impl<'a> ::flatbuffers::Follow<'a> for Color {
type Inner = Self; type Inner = Self;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let b = unsafe { ::flatbuffers::read_scalar_at::<i8>(buf, loc) };
let b = unsafe { ::flatbuffers::read_scalar_at::<i8>(buf, loc) }; Self(b)
Self(b) }
}
} }
impl ::flatbuffers::Push for Color { impl ::flatbuffers::Push for Color {
type Output = Color; type Output = Color;
#[inline] #[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
unsafe { ::flatbuffers::emplace_scalar::<i8>(dst, self.0) }; unsafe { ::flatbuffers::emplace_scalar::<i8>(dst, self.0) };
@@ -76,28 +67,26 @@ impl ::flatbuffers::Push for Color {
} }
impl ::flatbuffers::EndianScalar for Color { impl ::flatbuffers::EndianScalar for Color {
type Scalar = i8; type Scalar = i8;
#[inline]
#[inline] fn to_little_endian(self) -> i8 {
fn to_little_endian(self) -> i8 { self.0.to_le()
self.0.to_le() }
} #[inline]
#[allow(clippy::wrong_self_convention)]
#[inline] fn from_little_endian(v: i8) -> Self {
#[allow(clippy::wrong_self_convention)] let b = i8::from_le(v);
fn from_little_endian(v: i8) -> Self { Self(b)
let b = i8::from_le(v); }
Self(b)
}
} }
impl<'a> ::flatbuffers::Verifiable for Color { impl<'a> ::flatbuffers::Verifiable for Color {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
i8::run_verifier(v, pos) i8::run_verifier(v, pos)
} }
} }
impl ::flatbuffers::SimpleToVerifyInSlice for Color {} impl ::flatbuffers::SimpleToVerifyInSlice for Color {}
@@ -2,69 +2,60 @@
// @generated // @generated
extern crate alloc; extern crate alloc;
use super::*; use super::*;
#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] #[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; 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.")] #[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; 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.")] #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [ pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [
Equipment::NONE, Equipment::NONE,
Equipment::Weapon, Equipment::Weapon,
]; ];
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)] #[repr(transparent)]
pub struct Equipment(pub u8); pub struct Equipment(pub u8);
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
impl Equipment { impl Equipment {
pub const NONE: Self = Self(0); pub const NONE: Self = Self(0);
pub const Weapon: Self = Self(1); pub const Weapon: Self = Self(1);
pub const ENUM_MIN: u8 = 0; pub const ENUM_MIN: u8 = 0;
pub const ENUM_MAX: u8 = 1; pub const ENUM_MAX: u8 = 1;
pub const ENUM_VALUES: &'static [Self] = &[ pub const ENUM_VALUES: &'static [Self] = &[
Self::NONE, Self::NONE,
Self::Weapon, Self::Weapon,
]; ];
/// Returns the variant's name or "" if unknown.
/// Returns the variant's name or "" if unknown. pub fn variant_name(self) -> Option<&'static str> {
pub fn variant_name(self) -> Option<&'static str> { match self {
match self { Self::NONE => Some("NONE"),
Self::NONE => Some("NONE"), Self::Weapon => Some("Weapon"),
Self::Weapon => Some("Weapon"), _ => None,
_ => None,
}
} }
}
} }
impl ::core::fmt::Debug for Equipment { impl ::core::fmt::Debug for Equipment {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
if let Some(name) = self.variant_name() { if let Some(name) = self.variant_name() {
f.write_str(name) f.write_str(name)
} else { } else {
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0)) f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
}
} }
}
} }
impl<'a> ::flatbuffers::Follow<'a> for Equipment { impl<'a> ::flatbuffers::Follow<'a> for Equipment {
type Inner = Self; type Inner = Self;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let b = unsafe { ::flatbuffers::read_scalar_at::<u8>(buf, loc) };
let b = unsafe { ::flatbuffers::read_scalar_at::<u8>(buf, loc) }; Self(b)
Self(b) }
}
} }
impl ::flatbuffers::Push for Equipment { impl ::flatbuffers::Push for Equipment {
type Output = Equipment; type Output = Equipment;
#[inline] #[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
unsafe { ::flatbuffers::emplace_scalar::<u8>(dst, self.0) }; unsafe { ::flatbuffers::emplace_scalar::<u8>(dst, self.0) };
@@ -72,85 +63,75 @@ impl ::flatbuffers::Push for Equipment {
} }
impl ::flatbuffers::EndianScalar for Equipment { impl ::flatbuffers::EndianScalar for Equipment {
type Scalar = u8; type Scalar = u8;
#[inline]
#[inline] fn to_little_endian(self) -> u8 {
fn to_little_endian(self) -> u8 { self.0.to_le()
self.0.to_le() }
} #[inline]
#[allow(clippy::wrong_self_convention)]
#[inline] fn from_little_endian(v: u8) -> Self {
#[allow(clippy::wrong_self_convention)] let b = u8::from_le(v);
fn from_little_endian(v: u8) -> Self { Self(b)
let b = u8::from_le(v); }
Self(b)
}
} }
impl<'a> ::flatbuffers::Verifiable for Equipment { impl<'a> ::flatbuffers::Verifiable for Equipment {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
u8::run_verifier(v, pos) u8::run_verifier(v, pos)
} }
} }
impl ::flatbuffers::SimpleToVerifyInSlice for Equipment {} impl ::flatbuffers::SimpleToVerifyInSlice for Equipment {}
pub struct EquipmentUnionTableOffset {} pub struct EquipmentUnionTableOffset {}
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum EquipmentT { pub enum EquipmentT {
NONE, NONE,
Weapon(alloc::boxed::Box<WeaponT>), Weapon(alloc::boxed::Box<WeaponT>),
} }
impl Default for EquipmentT { impl Default for EquipmentT {
fn default() -> Self { fn default() -> Self {
Self::NONE Self::NONE
} }
} }
impl EquipmentT { impl EquipmentT {
pub fn equipment_type(&self) -> Equipment { pub fn equipment_type(&self) -> Equipment {
match self { match self {
Self::NONE => Equipment::NONE, Self::NONE => Equipment::NONE,
Self::Weapon(_) => Equipment::Weapon, Self::Weapon(_) => Equipment::Weapon,
}
} }
}
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(&self, fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>) -> Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>> { pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(&self, fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>) -> Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>> {
match self { match self {
Self::NONE => None, Self::NONE => None,
Self::Weapon(v) => Some(v.pack(fbb).as_union_value()), Self::Weapon(v) => Some(v.pack(fbb).as_union_value()),
}
} }
}
/// If the union variant matches, return the owned WeaponT, setting the union to 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>> { pub fn take_weapon(&mut self) -> Option<alloc::boxed::Box<WeaponT>> {
if let Self::Weapon(_) = self { if let Self::Weapon(_) = self {
let v = ::core::mem::replace(self, Self::NONE); let v = ::core::mem::replace(self, Self::NONE);
if let Self::Weapon(w) = v { if let Self::Weapon(w) = v {
Some(w) Some(w)
} else { } else {
unreachable!() unreachable!()
} }
} else { } else {
None 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,225 +2,212 @@
// @generated // @generated
extern crate alloc; extern crate alloc;
use super::*; use super::*;
pub enum MonsterOffset {} pub enum MonsterOffset {}
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub struct Monster<'a> { pub struct Monster<'a> {
pub _tab: ::flatbuffers::Table<'a>, pub _tab: ::flatbuffers::Table<'a>,
} }
impl<'a> ::flatbuffers::Follow<'a> for Monster<'a> { impl<'a> ::flatbuffers::Follow<'a> for Monster<'a> {
type Inner = Monster<'a>; type Inner = Monster<'a>;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } }
}
} }
impl<'a> Monster<'a> { impl<'a> Monster<'a> {
pub const VT_POS: ::flatbuffers::VOffsetT = 4; pub const VT_POS: ::flatbuffers::VOffsetT = 4;
pub const VT_MANA: ::flatbuffers::VOffsetT = 6; pub const VT_MANA: ::flatbuffers::VOffsetT = 6;
pub const VT_HP: ::flatbuffers::VOffsetT = 8; pub const VT_HP: ::flatbuffers::VOffsetT = 8;
pub const VT_NAME: ::flatbuffers::VOffsetT = 10; pub const VT_NAME: ::flatbuffers::VOffsetT = 10;
pub const VT_INVENTORY: ::flatbuffers::VOffsetT = 14; pub const VT_INVENTORY: ::flatbuffers::VOffsetT = 14;
pub const VT_COLOR: ::flatbuffers::VOffsetT = 16; pub const VT_COLOR: ::flatbuffers::VOffsetT = 16;
pub const VT_WEAPONS: ::flatbuffers::VOffsetT = 18; pub const VT_WEAPONS: ::flatbuffers::VOffsetT = 18;
pub const VT_EQUIPPED_TYPE: ::flatbuffers::VOffsetT = 20; pub const VT_EQUIPPED_TYPE: ::flatbuffers::VOffsetT = 20;
pub const VT_EQUIPPED: ::flatbuffers::VOffsetT = 22; pub const VT_EQUIPPED: ::flatbuffers::VOffsetT = 22;
pub const VT_PATH: ::flatbuffers::VOffsetT = 24; pub const VT_PATH: ::flatbuffers::VOffsetT = 24;
pub const fn get_fully_qualified_name() -> &'static str { pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Monster" "MyGame.Sample.Monster"
} }
#[inline] #[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Monster { _tab: table } 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()
}
#[allow(unused_mut)] pub fn unpack(&self) -> MonsterT {
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( let pos = self.pos().map(|x| {
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, x.unpack()
args: &'args MonsterArgs<'args> });
) -> ::flatbuffers::WIPOffset<Monster<'bldr>> { let mana = self.mana();
let mut builder = MonsterBuilder::new(_fbb); let hp = self.hp();
if let Some(x) = args.path { builder.add_path(x); } let name = self.name().map(|x| {
if let Some(x) = args.equipped { builder.add_equipped(x); } alloc::string::ToString::to_string(x)
if let Some(x) = args.weapons { builder.add_weapons(x); } });
if let Some(x) = args.inventory { builder.add_inventory(x); } let inventory = self.inventory().map(|x| {
if let Some(x) = args.name { builder.add_name(x); } x.into_iter().collect()
if let Some(x) = args.pos { builder.add_pos(x); } });
builder.add_hp(args.hp); let color = self.color();
builder.add_mana(args.mana); let weapons = self.weapons().map(|x| {
builder.add_equipped_type(args.equipped_type); x.iter().map(|t| t.unpack()).collect()
builder.add_color(args.color); });
builder.finish() 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 fn unpack(&self) -> MonsterT { #[inline]
let pos = self.pos().map(|x| { pub fn pos(&self) -> Option<&'a Vec3> {
x.unpack() // Safety:
}); // Created from valid Table for this object
let mana = self.mana(); // which contains a valid value in this slot
let hp = self.hp(); unsafe { self._tab.get::<Vec3>(Monster::VT_POS, None)}
let name = self.name().map(|x| { }
alloc::string::ToString::to_string(x) #[inline]
}); pub fn mana(&self) -> i16 {
let inventory = self.inventory().map(|x| { // Safety:
x.into_iter().collect() // Created from valid Table for this object
}); // which contains a valid value in this slot
let color = self.color(); unsafe { self._tab.get::<i16>(Monster::VT_MANA, Some(150)).unwrap()}
let weapons = self.weapons().map(|x| { }
x.iter().map(|t| t.unpack()).collect() #[inline]
}); pub fn hp(&self) -> i16 {
let equipped = match self.equipped_type() { // Safety:
Equipment::NONE => EquipmentT::NONE, // Created from valid Table for this object
Equipment::Weapon => EquipmentT::Weapon(alloc::boxed::Box::new( // which contains a valid value in this slot
self.equipped_as_weapon() unsafe { self._tab.get::<i16>(Monster::VT_HP, Some(100)).unwrap()}
.expect("Invalid union table, expected `Equipment::Weapon`.") }
.unpack() #[inline]
)), pub fn name(&self) -> Option<&'a str> {
_ => EquipmentT::NONE, // Safety:
}; // Created from valid Table for this object
let path = self.path().map(|x| { // which contains a valid value in this slot
x.iter().map(|t| t.unpack()).collect() unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None)}
}); }
MonsterT { #[inline]
pos, pub fn inventory(&self) -> Option<::flatbuffers::Vector<'a, u8>> {
mana, // Safety:
hp, // Created from valid Table for this object
name, // which contains a valid value in this slot
inventory, unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, u8>>>(Monster::VT_INVENTORY, None)}
color, }
weapons, #[inline]
equipped, pub fn color(&self) -> Color {
path, // 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 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<'_> { impl ::flatbuffers::Verifiable for Monster<'_> {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)? v.visit_table(pos)?
.visit_field::<Vec3>("pos", Self::VT_POS, false)? .visit_field::<Vec3>("pos", Self::VT_POS, false)?
.visit_field::<i16>("mana", Self::VT_MANA, false)? .visit_field::<i16>("mana", Self::VT_MANA, false)?
.visit_field::<i16>("hp", Self::VT_HP, false)? .visit_field::<i16>("hp", Self::VT_HP, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, 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::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, u8>>>("inventory", Self::VT_INVENTORY, false)?
.visit_field::<Color>("color", Self::VT_COLOR, false)? .visit_field::<Color>("color", Self::VT_COLOR, false)?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset<Weapon>>>>("weapons", Self::VT_WEAPONS, 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| { .visit_union::<Equipment, _>("equipped_type", Self::VT_EQUIPPED_TYPE, "equipped", Self::VT_EQUIPPED, false, |key, v, pos| {
match key { match key {
Equipment::Weapon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos), Equipment::Weapon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos),
_ => Ok(()), _ => Ok(()),
} }
})? })?
.visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, Vec3>>>("path", Self::VT_PATH, false)? .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, Vec3>>>("path", Self::VT_PATH, false)?
.finish(); .finish();
Ok(()) Ok(())
} }
} }
pub struct MonsterArgs<'a> { pub struct MonsterArgs<'a> {
pub pos: Option<&'a Vec3>, pub pos: Option<&'a Vec3>,
pub mana: i16, pub mana: i16,
@@ -233,273 +220,246 @@ pub struct MonsterArgs<'a> {
pub equipped: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, pub equipped: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>,
pub path: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, Vec3>>>, pub path: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, Vec3>>>,
} }
impl<'a> Default for MonsterArgs<'a> { impl<'a> Default for MonsterArgs<'a> {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
MonsterArgs { MonsterArgs {
pos: None, pos: None,
mana: 150, mana: 150,
hp: 100, hp: 100,
name: None, name: None,
inventory: None, inventory: None,
color: Color::Blue, color: Color::Blue,
weapons: None, weapons: None,
equipped_type: Equipment::NONE, equipped_type: Equipment::NONE,
equipped: None, equipped: None,
path: None, path: None,
}
} }
}
} }
pub struct MonsterBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { pub struct MonsterBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
} }
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> MonsterBuilder<'a, 'b, A> { impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> MonsterBuilder<'a, 'b, A> {
#[inline] #[inline]
pub fn add_pos(&mut self, pos: &Vec3) { pub fn add_pos(&mut self, pos: &Vec3) {
self.fbb_.push_slot_always::<&Vec3>(Monster::VT_POS, pos); self.fbb_.push_slot_always::<&Vec3>(Monster::VT_POS, pos);
} }
#[inline]
#[inline] pub fn add_mana(&mut self, mana: i16) {
pub fn add_mana(&mut self, mana: i16) { self.fbb_.push_slot::<i16>(Monster::VT_MANA, mana, 150);
self.fbb_.push_slot::<i16>(Monster::VT_MANA, mana, 150); }
} #[inline]
pub fn add_hp(&mut self, hp: i16) {
#[inline] self.fbb_.push_slot::<i16>(Monster::VT_HP, hp, 100);
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_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) { #[inline]
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_NAME, name); 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] #[inline]
pub fn add_inventory(&mut self, inventory: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , u8>>) { pub fn add_color(&mut self, color: Color) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_INVENTORY, inventory); self.fbb_.push_slot::<Color>(Monster::VT_COLOR, color, Color::Blue);
} }
#[inline]
#[inline] pub fn add_weapons(&mut self, weapons: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset<Weapon<'b >>>>) {
pub fn add_color(&mut self, color: Color) { self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_WEAPONS, weapons);
self.fbb_.push_slot::<Color>(Monster::VT_COLOR, color, Color::Blue); }
} #[inline]
pub fn add_equipped_type(&mut self, equipped_type: Equipment) {
#[inline] self.fbb_.push_slot::<Equipment>(Monster::VT_EQUIPPED_TYPE, equipped_type, Equipment::NONE);
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(&mut self, equipped: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_EQUIPPED, equipped);
#[inline] }
pub fn add_equipped_type(&mut self, equipped_type: Equipment) { #[inline]
self.fbb_.push_slot::<Equipment>(Monster::VT_EQUIPPED_TYPE, equipped_type, Equipment::NONE); 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] #[inline]
pub fn add_equipped(&mut self, equipped: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> MonsterBuilder<'a, 'b, A> {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Monster::VT_EQUIPPED, equipped); let start = _fbb.start_table();
} MonsterBuilder {
fbb_: _fbb,
#[inline] start_: start,
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<'_> { impl ::core::fmt::Debug for Monster<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Monster"); let mut ds = f.debug_struct("Monster");
ds.field("pos", &self.pos()); ds.field("pos", &self.pos());
ds.field("mana", &self.mana()); ds.field("mana", &self.mana());
ds.field("hp", &self.hp()); ds.field("hp", &self.hp());
ds.field("name", &self.name()); ds.field("name", &self.name());
ds.field("inventory", &self.inventory()); ds.field("inventory", &self.inventory());
ds.field("color", &self.color()); ds.field("color", &self.color());
ds.field("weapons", &self.weapons()); ds.field("weapons", &self.weapons());
ds.field("equipped_type", &self.equipped_type()); ds.field("equipped_type", &self.equipped_type());
match self.equipped_type() { match self.equipped_type() {
Equipment::Weapon => { Equipment::Weapon => {
if let Some(x) = self.equipped_as_weapon() { if let Some(x) = self.equipped_as_weapon() {
ds.field("equipped", &x) ds.field("equipped", &x)
} else { } else {
ds.field("equipped", &"InvalidFlatbuffer: Union discriminant does not match value.") ds.field("equipped", &"InvalidFlatbuffer: Union discriminant does not match value.")
} }
}, },
_ => { _ => {
let x: Option<()> = None; let x: Option<()> = None;
ds.field("equipped", &x) ds.field("equipped", &x)
}, },
}; };
ds.field("path", &self.path()); ds.field("path", &self.path());
ds.finish() ds.finish()
} }
} }
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct MonsterT { pub struct MonsterT {
pub pos: Option<Vec3T>, pub pos: Option<Vec3T>,
pub mana: i16, pub mana: i16,
pub hp: i16, pub hp: i16,
pub name: Option<alloc::string::String>, pub name: Option<alloc::string::String>,
pub inventory: Option<alloc::vec::Vec<u8>>, pub inventory: Option<alloc::vec::Vec<u8>>,
pub color: Color, pub color: Color,
pub weapons: Option<alloc::vec::Vec<WeaponT>>, pub weapons: Option<alloc::vec::Vec<WeaponT>>,
pub equipped: EquipmentT, pub equipped: EquipmentT,
pub path: Option<alloc::vec::Vec<Vec3T>>, pub path: Option<alloc::vec::Vec<Vec3T>>,
} }
impl Default for MonsterT { impl Default for MonsterT {
fn default() -> Self { fn default() -> Self {
Self { Self {
pos: None, pos: None,
mana: 150, mana: 150,
hp: 100, hp: 100,
name: None, name: None,
inventory: None, inventory: None,
color: Color::Blue, color: Color::Blue,
weapons: None, weapons: None,
equipped: EquipmentT::NONE, equipped: EquipmentT::NONE,
path: None, path: None,
}
} }
}
} }
impl MonsterT { impl MonsterT {
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>( pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self, &self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A> _fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Monster<'b>> { ) -> ::flatbuffers::WIPOffset<Monster<'b>> {
let pos_tmp = self.pos.as_ref().map(|x| x.pack()); let pos_tmp = self.pos.as_ref().map(|x| x.pack());
let pos = pos_tmp.as_ref(); let pos = pos_tmp.as_ref();
let mana = self.mana; let mana = self.mana;
let hp = self.hp; let hp = self.hp;
let name = self.name.as_ref().map(|x|{ let name = self.name.as_ref().map(|x|{
_fbb.create_string(x) _fbb.create_string(x)
}); });
let inventory = self.inventory.as_ref().map(|x|{ let inventory = self.inventory.as_ref().map(|x|{
_fbb.create_vector(x) _fbb.create_vector(x)
}); });
let color = self.color; let color = self.color;
let weapons = self.weapons.as_ref().map(|x|{ 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 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_type = self.equipped.equipment_type();
let equipped = self.equipped.pack(_fbb); let equipped = self.equipped.pack(_fbb);
let path = self.path.as_ref().map(|x|{ let path = self.path.as_ref().map(|x|{
let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w) let w: alloc::vec::Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
}); });
Monster::create(_fbb, &MonsterArgs{ Monster::create(_fbb, &MonsterArgs{
pos, pos,
mana, mana,
hp, hp,
name, name,
inventory, inventory,
color, color,
weapons, weapons,
equipped_type, equipped_type,
equipped, equipped,
path, path,
}) })
} }
} }
#[inline]
/// Verifies that a buffer of bytes contains a `Monster` /// Verifies that a buffer of bytes contains a `Monster`
/// and returns it. /// and returns it.
/// Note that verification is still experimental and may not /// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the /// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use /// previous, unchecked, behavior use
/// `root_as_monster_unchecked`. /// `root_as_monster_unchecked`.
#[inline]
pub fn root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> { pub fn root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root::<Monster>(buf) ::flatbuffers::root::<Monster>(buf)
} }
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed /// Verifies that a buffer of bytes contains a size prefixed
/// `Monster` and returns it. /// `Monster` and returns it.
/// Note that verification is still experimental and may not /// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the /// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use /// previous, unchecked, behavior use
/// `size_prefixed_root_as_monster_unchecked`. /// `size_prefixed_root_as_monster_unchecked`.
#[inline]
pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> { pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster<'_>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root::<Monster>(buf) ::flatbuffers::size_prefixed_root::<Monster>(buf)
} }
#[inline]
/// Verifies, with the given options, that a buffer of bytes /// Verifies, with the given options, that a buffer of bytes
/// contains a `Monster` and returns it. /// contains a `Monster` and returns it.
/// Note that verification is still experimental and may not /// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the /// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use /// previous, unchecked, behavior use
/// `root_as_monster_unchecked`. /// `root_as_monster_unchecked`.
#[inline]
pub fn root_as_monster_with_opts<'b, 'o>( pub fn root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions, opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8], buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> { ) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::root_with_opts::<Monster<'b>>(opts, buf) ::flatbuffers::root_with_opts::<Monster<'b>>(opts, buf)
} }
#[inline]
/// Verifies, with the given verifier options, that a buffer of /// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Monster` and returns /// bytes contains a size prefixed `Monster` and returns
/// it. Note that verification is still experimental and may not /// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the /// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use /// previous, unchecked, behavior use
/// `root_as_monster_unchecked`. /// `root_as_monster_unchecked`.
#[inline]
pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>( pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>(
opts: &'o ::flatbuffers::VerifierOptions, opts: &'o ::flatbuffers::VerifierOptions,
buf: &'b [u8], buf: &'b [u8],
) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> { ) -> Result<Monster<'b>, ::flatbuffers::InvalidFlatbuffer> {
::flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf) ::flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf)
} }
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Monster and returns it. /// Assumes, without verification, that a buffer of bytes contains a Monster and returns it.
/// # Safety /// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Monster`. /// Callers must trust the given bytes do indeed contain a valid `Monster`.
#[inline]
pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> { pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::root_unchecked::<Monster>(buf) } unsafe { ::flatbuffers::root_unchecked::<Monster>(buf) }
} }
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it. /// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it.
/// # Safety /// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`. /// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`.
#[inline]
pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> { pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster<'_> {
unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Monster>(buf) } unsafe { ::flatbuffers::size_prefixed_root_unchecked::<Monster>(buf) }
} }
#[inline] #[inline]
pub fn finish_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>( pub fn finish_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(
fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
root: ::flatbuffers::WIPOffset<Monster<'a>> root: ::flatbuffers::WIPOffset<Monster<'a>>) {
) { fbb.finish(root, None);
fbb.finish(root, None);
} }
#[inline] #[inline]
pub fn finish_size_prefixed_monster_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>( 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: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, fbb.finish_size_prefixed(root, None);
root: ::flatbuffers::WIPOffset<Monster<'a>>
) {
fbb.finish_size_prefixed(root, None);
} }
@@ -2,57 +2,47 @@
// @generated // @generated
extern crate alloc; extern crate alloc;
use super::*; use super::*;
// struct Vec3, aligned to 4 // struct Vec3, aligned to 4
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub struct Vec3(pub [u8; 12]); pub struct Vec3(pub [u8; 12]);
impl Default for Vec3 {
impl Default for Vec3 { fn default() -> Self {
fn default() -> Self { Self([0; 12])
Self([0; 12]) }
}
} }
impl ::core::fmt::Debug for Vec3 { impl ::core::fmt::Debug for Vec3 {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
f.debug_struct("Vec3") f.debug_struct("Vec3")
.field("x", &self.x()) .field("x", &self.x())
.field("y", &self.y()) .field("y", &self.y())
.field("z", &self.z()) .field("z", &self.z())
.finish() .finish()
} }
} }
impl ::flatbuffers::SimpleToVerifyInSlice for Vec3 {} impl ::flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl<'a> ::flatbuffers::Follow<'a> for Vec3 { impl<'a> ::flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3; type Inner = &'a Vec3;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe { <&'a Vec3>::follow(buf, loc) }
unsafe { <&'a Vec3>::follow(buf, loc) } }
}
} }
impl<'a> ::flatbuffers::Follow<'a> for &'a Vec3 { impl<'a> ::flatbuffers::Follow<'a> for &'a Vec3 {
type Inner = &'a Vec3; type Inner = &'a Vec3;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { unsafe { ::flatbuffers::follow_cast_ref::<Vec3>(buf, loc) }
unsafe { ::flatbuffers::follow_cast_ref::<Vec3>(buf, loc) } }
}
} }
impl<'b> ::flatbuffers::Push for Vec3 { impl<'b> ::flatbuffers::Push for Vec3 {
type Output = Vec3; type Output = Vec3;
#[inline] #[inline]
unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { 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()) }; 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); dst.copy_from_slice(src);
} }
#[inline] #[inline]
fn alignment() -> ::flatbuffers::PushAlignment { fn alignment() -> ::flatbuffers::PushAlignment {
::flatbuffers::PushAlignment::new(4) ::flatbuffers::PushAlignment::new(4)
@@ -60,150 +50,141 @@ impl<'b> ::flatbuffers::Push for Vec3 {
} }
impl<'a> ::flatbuffers::Verifiable for Vec3 { impl<'a> ::flatbuffers::Verifiable for Vec3 {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.in_buffer::<Self>(pos) v.in_buffer::<Self>(pos)
} }
} }
impl<'a> Vec3 { impl<'a> Vec3 {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
x: f32, x: f32,
y: f32, y: f32,
z: f32, z: f32,
) -> Self { ) -> Self {
let mut s = Self([0; 12]); let mut s = Self([0; 12]);
s.set_x(x); s.set_x(x);
s.set_y(y); s.set_y(y);
s.set_z(z); s.set_z(z);
s s
} }
pub const fn get_fully_qualified_name() -> &'static str { pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Vec3" "MyGame.Sample.Vec3"
} }
pub fn x(&self) -> f32 { pub fn x(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit(); let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe { ::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
self.0[0..].as_ptr(), self.0[0..].as_ptr(),
mem.as_mut_ptr() as *mut u8, mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
mem.assume_init() mem.assume_init()
}) })
} }
pub fn set_x(&mut self, x: f32) { pub fn set_x(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
unsafe { unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8, &x_le as *const _ as *const u8,
self.0[0..].as_mut_ptr(), self.0[0..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
}
} }
}
pub fn y(&self) -> f32 { pub fn y(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit(); let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe { ::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
self.0[4..].as_ptr(), self.0[4..].as_ptr(),
mem.as_mut_ptr() as *mut u8, mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
mem.assume_init() mem.assume_init()
}) })
} }
pub fn set_y(&mut self, x: f32) { pub fn set_y(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
unsafe { unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8, &x_le as *const _ as *const u8,
self.0[4..].as_mut_ptr(), self.0[4..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
}
} }
}
pub fn z(&self) -> f32 { pub fn z(&self) -> f32 {
let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit(); let mut mem = ::core::mem::MaybeUninit::<<f32 as ::flatbuffers::EndianScalar>::Scalar>::uninit();
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
::flatbuffers::EndianScalar::from_little_endian(unsafe { ::flatbuffers::EndianScalar::from_little_endian(unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
self.0[8..].as_ptr(), self.0[8..].as_ptr(),
mem.as_mut_ptr() as *mut u8, mem.as_mut_ptr() as *mut u8,
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
mem.assume_init() mem.assume_init()
}) })
} }
pub fn set_z(&mut self, x: f32) { pub fn set_z(&mut self, x: f32) {
let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); let x_le = ::flatbuffers::EndianScalar::to_little_endian(x);
// Safety: // Safety:
// Created from a valid Table for this object // Created from a valid Table for this object
// Which contains a valid value in this slot // Which contains a valid value in this slot
unsafe { unsafe {
::core::ptr::copy_nonoverlapping( ::core::ptr::copy_nonoverlapping(
&x_le as *const _ as *const u8, &x_le as *const _ as *const u8,
self.0[8..].as_mut_ptr(), self.0[8..].as_mut_ptr(),
::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(), ::core::mem::size_of::<<f32 as ::flatbuffers::EndianScalar>::Scalar>(),
); );
}
} }
}
pub fn unpack(&self) -> Vec3T { pub fn unpack(&self) -> Vec3T {
Vec3T { Vec3T {
x: self.x(), x: self.x(),
y: self.y(), y: self.y(),
z: self.z(), z: self.z(),
}
} }
}
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Default)]
pub struct Vec3T { pub struct Vec3T {
pub x: f32, pub x: f32,
pub y: f32, pub y: f32,
pub z: f32, pub z: f32,
} }
impl Default for Vec3T { impl Vec3T {
fn default() -> Self { pub fn pack(&self) -> Vec3 {
Self { Vec3::new(
x: 0.0, self.x,
y: 0.0, self.y,
z: 0.0, self.z,
} )
} }
} }
impl Vec3T {
pub fn pack(&self) -> Vec3 {
Vec3::new(
self.x,
self.y,
self.z,
)
}
}
@@ -2,172 +2,159 @@
// @generated // @generated
extern crate alloc; extern crate alloc;
use super::*; use super::*;
pub enum WeaponOffset {} pub enum WeaponOffset {}
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub struct Weapon<'a> { pub struct Weapon<'a> {
pub _tab: ::flatbuffers::Table<'a>, pub _tab: ::flatbuffers::Table<'a>,
} }
impl<'a> ::flatbuffers::Follow<'a> for Weapon<'a> { impl<'a> ::flatbuffers::Follow<'a> for Weapon<'a> {
type Inner = Weapon<'a>; type Inner = Weapon<'a>;
#[inline]
#[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } }
Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } }
}
} }
impl<'a> Weapon<'a> { impl<'a> Weapon<'a> {
pub const VT_NAME: ::flatbuffers::VOffsetT = 4; pub const VT_NAME: ::flatbuffers::VOffsetT = 4;
pub const VT_DAMAGE: ::flatbuffers::VOffsetT = 6; pub const VT_DAMAGE: ::flatbuffers::VOffsetT = 6;
pub const fn get_fully_qualified_name() -> &'static str { pub const fn get_fully_qualified_name() -> &'static str {
"MyGame.Sample.Weapon" "MyGame.Sample.Weapon"
} }
#[inline] #[inline]
pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self {
Weapon { _tab: table } 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()
}
#[allow(unused_mut)] pub fn unpack(&self) -> WeaponT {
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( let name = self.name().map(|x| {
_fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, alloc::string::ToString::to_string(x)
args: &'args WeaponArgs<'args> });
) -> ::flatbuffers::WIPOffset<Weapon<'bldr>> { let damage = self.damage();
let mut builder = WeaponBuilder::new(_fbb); WeaponT {
if let Some(x) = args.name { builder.add_name(x); } name,
builder.add_damage(args.damage); damage,
builder.finish()
} }
}
pub fn unpack(&self) -> WeaponT { #[inline]
let name = self.name().map(|x| { pub fn name(&self) -> Option<&'a str> {
alloc::string::ToString::to_string(x) // Safety:
}); // Created from valid Table for this object
let damage = self.damage(); // which contains a valid value in this slot
WeaponT { unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(Weapon::VT_NAME, None)}
name, }
damage, #[inline]
} pub fn damage(&self) -> i16 {
} // Safety:
// Created from valid Table for this object
#[inline] // which contains a valid value in this slot
pub fn name(&self) -> Option<&'a str> { unsafe { self._tab.get::<i16>(Weapon::VT_DAMAGE, Some(0)).unwrap()}
// 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<'_> { impl ::flatbuffers::Verifiable for Weapon<'_> {
#[inline] #[inline]
fn run_verifier( fn run_verifier(
v: &mut ::flatbuffers::Verifier, pos: usize v: &mut ::flatbuffers::Verifier, pos: usize
) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> {
v.visit_table(pos)? v.visit_table(pos)?
.visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)? .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
.visit_field::<i16>("damage", Self::VT_DAMAGE, false)? .visit_field::<i16>("damage", Self::VT_DAMAGE, false)?
.finish(); .finish();
Ok(()) Ok(())
} }
} }
pub struct WeaponArgs<'a> { pub struct WeaponArgs<'a> {
pub name: Option<::flatbuffers::WIPOffset<&'a str>>, pub name: Option<::flatbuffers::WIPOffset<&'a str>>,
pub damage: i16, pub damage: i16,
} }
impl<'a> Default for WeaponArgs<'a> { impl<'a> Default for WeaponArgs<'a> {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
WeaponArgs { WeaponArgs {
name: None, name: None,
damage: 0, damage: 0,
}
} }
}
} }
pub struct WeaponBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { pub struct WeaponBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> {
fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>,
start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>,
} }
impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> WeaponBuilder<'a, 'b, A> { impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> WeaponBuilder<'a, 'b, A> {
#[inline] #[inline]
pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) { pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) {
self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Weapon::VT_NAME, name); self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Weapon::VT_NAME, name);
} }
#[inline]
#[inline] pub fn add_damage(&mut self, damage: i16) {
pub fn add_damage(&mut self, damage: i16) { self.fbb_.push_slot::<i16>(Weapon::VT_DAMAGE, damage, 0);
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> {
#[inline] let start = _fbb.start_table();
pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> WeaponBuilder<'a, 'b, A> { WeaponBuilder {
let start = _fbb.start_table(); fbb_: _fbb,
WeaponBuilder { start_: start,
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<'_> { impl ::core::fmt::Debug for Weapon<'_> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut ds = f.debug_struct("Weapon"); let mut ds = f.debug_struct("Weapon");
ds.field("name", &self.name()); ds.field("name", &self.name());
ds.field("damage", &self.damage()); ds.field("damage", &self.damage());
ds.finish() ds.finish()
} }
} }
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct WeaponT { pub struct WeaponT {
pub name: Option<alloc::string::String>, pub name: Option<alloc::string::String>,
pub damage: i16, pub damage: i16,
} }
impl Default for WeaponT { impl Default for WeaponT {
fn default() -> Self { fn default() -> Self {
Self { Self {
name: None, name: None,
damage: 0, damage: 0,
}
} }
}
} }
impl WeaponT { impl WeaponT {
pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>( pub fn pack<'b, A: ::flatbuffers::Allocator + 'b>(
&self, &self,
_fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A> _fbb: &mut ::flatbuffers::FlatBufferBuilder<'b, A>
) -> ::flatbuffers::WIPOffset<Weapon<'b>> { ) -> ::flatbuffers::WIPOffset<Weapon<'b>> {
let name = self.name.as_ref().map(|x|{ let name = self.name.as_ref().map(|x|{
_fbb.create_string(x) _fbb.create_string(x)
}); });
let damage = self.damage; let damage = self.damage;
Weapon::create(_fbb, &WeaponArgs{ Weapon::create(_fbb, &WeaponArgs{
name, name,
damage, damage,
}) })
} }
} }
+15 -17
View File
@@ -251,6 +251,21 @@ flatc(
schema="vector_table_naked_ptr.fbs", 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( flatc(
BASE_OPTS + CPP_OPTS + CS_OPTS + JAVA_OPTS + KOTLIN_OPTS + PHP_OPTS, BASE_OPTS + CPP_OPTS + CS_OPTS + JAVA_OPTS + KOTLIN_OPTS + PHP_OPTS,
prefix="union_vector", prefix="union_vector",
@@ -394,11 +409,6 @@ flatc(
schema="native_inline_table_test.fbs", schema="native_inline_table_test.fbs",
) )
flatc(
["--cpp", "--gen-compare", "--gen-mutable", "--gen-object-api", "--reflect-names"],
schema="cross_namespace_pack_test.fbs",
)
flatc( flatc(
RUST_OPTS, RUST_OPTS,
prefix="arrays_test", prefix="arrays_test",
@@ -422,11 +432,6 @@ flatc(
schema="nested_union_test.fbs", schema="nested_union_test.fbs",
) )
flatc(
["--python", "--gen-object-api"],
schema="union_name_test.fbs",
)
flatc( flatc(
NO_INCL_OPTS + CPP_OPTS, NO_INCL_OPTS + CPP_OPTS,
schema="default_vectors_strings_test.fbs", schema="default_vectors_strings_test.fbs",
@@ -527,13 +532,6 @@ flatc(
cwd=swift_code_gen, 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 Tests
swift_Wasm_prefix = "swift/Wasm.tests/Tests/FlatBuffers.Test.Swift.WasmTests" swift_Wasm_prefix = "swift/Wasm.tests/Tests/FlatBuffers.Test.Swift.WasmTests"
flatc( flatc(
+2 -3
View File
@@ -20,7 +20,6 @@ from util import flatc, root_path
grpc_examples_path = Path(root_path, "grpc/examples") grpc_examples_path = Path(root_path, "grpc/examples")
greeter_schema = str(Path(grpc_examples_path, "greeter.fbs")) greeter_schema = str(Path(grpc_examples_path, "greeter.fbs"))
greeter_schema_v2 = str(Path(grpc_examples_path, "greeter_v2.fbs"))
COMMON_ARGS = [ COMMON_ARGS = [
"--grpc", "--grpc",
@@ -55,8 +54,8 @@ def GenerateGRPCExamples():
"--swift", "--swift",
"--gen-json-emit", "--gen-json-emit",
], ],
schema=greeter_schema_v2, schema=greeter_schema,
cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Models"), cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Model"),
) )
flatc( flatc(
+3 -1
View File
@@ -126,7 +126,9 @@ static BinarySection GenerateMissingSection(const uint64_t offset,
std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() { std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
if (bfbs_ != nullptr && bfbs_length_ != 0) { if (bfbs_ != nullptr && bfbs_length_ != 0) {
flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_)); flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
if (!reflection::VerifySchemaBuffer(verifier)) { if ((is_size_prefixed_ &&
!reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
!reflection::VerifySchemaBuffer(verifier)) {
return {}; return {};
} }
} }
+9
View File
@@ -145,6 +145,12 @@ const static FlatCOption flatc_options[] = {
{"", "cpp-str-flex-ctor", "", {"", "cpp-str-flex-ctor", "",
"Don't construct custom string types by passing std::string from " "Don't construct custom string types by passing std::string from "
"Flatbuffers, but (char* + length)."}, "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", {"", "cpp-field-case-style", "STYLE",
"Generate C++ fields using selected case style. Supported STYLE values: * " "Generate C++ fields using selected case style. Supported STYLE values: * "
"'unchanged' - leave unchanged (default) * 'upper' - schema snake_case " "'unchanged' - leave unchanged (default) * 'upper' - schema snake_case "
@@ -545,6 +551,9 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
opts.cpp_object_api_string_type = argv[argi]; opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--cpp-str-flex-ctor") { } else if (arg == "--cpp-str-flex-ctor") {
opts.cpp_object_api_string_flexible_constructor = true; 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") { } else if (arg == "--no-cpp-direct-copy") {
opts.cpp_direct_copy = false; opts.cpp_direct_copy = false;
} else if (arg == "--cpp-field-case-style") { } else if (arg == "--cpp-field-case-style") {
+284 -44
View File
@@ -257,6 +257,19 @@ class CppGenerator : public BaseGenerator {
code_ += " FLATBUFFERS_VERSION_REVISION == " + code_ += " FLATBUFFERS_VERSION_REVISION == " +
std::to_string(FLATBUFFERS_VERSION_REVISION) + ","; std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
code_ += " \"Non-compatible flatbuffers version included\");"; 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() { void GenIncludeDependencies() {
@@ -529,6 +542,8 @@ class CppGenerator : public BaseGenerator {
code_ += ""; code_ += "";
} }
GenerateBigfootRefForwardDecls();
// Generate preablmle code for mini reflection. // Generate preablmle code for mini reflection.
if (opts_.mini_reflect != IDLOptions::kNone) { if (opts_.mini_reflect != IDLOptions::kNone) {
// To break cyclic dependencies, first pre-declare all tables/structs. // To break cyclic dependencies, first pre-declare all tables/structs.
@@ -758,6 +773,8 @@ class CppGenerator : public BaseGenerator {
if (cur_name_space_) SetNameSpace(nullptr); if (cur_name_space_) SetNameSpace(nullptr);
GenerateBigfootRefImpls();
// Close the include guard. // Close the include guard.
code_ += "#endif // " + include_guard; code_ += "#endif // " + include_guard;
@@ -892,6 +909,24 @@ class CppGenerator : public BaseGenerator {
return opts_.gen_nullable ? " _Nullable " : ""; 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, static std::string NativeName(const std::string& name, const StructDef* sd,
const IDLOptions& opts) { const IDLOptions& opts) {
// If the table is a native_type, return the native_type name. // If the table is a native_type, return the native_type name.
@@ -937,6 +972,23 @@ class CppGenerator : public BaseGenerator {
"std::string"; // Only for custom string types. "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, std::string GenTypeNativePtr(const std::string& type, const FieldDef* field,
bool is_constructor) { bool is_constructor) {
auto& ptr_type = PtrType(field); auto& ptr_type = PtrType(field);
@@ -974,20 +1026,21 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_VECTOR64: case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field); const auto type_name = GenTypeNative(type.VectorType(), true, field);
if (type.struct_def && const auto vector_type = NativeVectorType(&field);
if (vector_type == "std::vector" && type.struct_def &&
type.struct_def->attributes.Lookup("native_custom_alloc")) { type.struct_def->attributes.Lookup("native_custom_alloc")) {
auto native_custom_alloc = auto native_custom_alloc =
type.struct_def->attributes.Lookup("native_custom_alloc"); type.struct_def->attributes.Lookup("native_custom_alloc");
return "std::vector<" + type_name + "," + return "std::vector<" + type_name + "," +
native_custom_alloc->constant + "<" + type_name + ">>"; native_custom_alloc->constant + "<" + type_name + ">>";
} else { } else {
return "std::vector<" + type_name + ">"; return vector_type + "<" + type_name + ">";
} }
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
auto type_name = WrapInNameSpace(*type.struct_def); auto type_name = WrapInNameSpace(*type.struct_def);
if (IsStruct(type)) { if (IsStruct(type)) {
auto native_type = type.struct_def->attributes.Lookup("native_type"); auto native_type = EffectiveNativeType(field, *type.struct_def);
if (native_type) { if (native_type) {
type_name = native_type->constant; type_name = native_type->constant;
} }
@@ -1979,7 +2032,7 @@ class CppGenerator : public BaseGenerator {
const std::string& full_type = const std::string& full_type =
(cpp_type (cpp_type
? (IsVector(field.value.type) ? (IsVector(field.value.type)
? "std::vector<" + ? NativeVectorType(&field) + "<" +
GenTypeNativePtr(cpp_type->constant, &field, GenTypeNativePtr(cpp_type->constant, &field,
false) + false) +
"> " "> "
@@ -2779,17 +2832,15 @@ class CppGenerator : public BaseGenerator {
get_call += ">(" + offset_str + ");"; get_call += ">(" + offset_str + ");";
code_ += get_call; code_ += get_call;
} else if (IsString(type) && field.value.constant != "0") { } else if (IsString(type) && field.value.constant != "0") {
std::string escaped; // TODO: Add logic to always convert the string to a valid C++ string
flatbuffers::EscapeString(field.value.constant.c_str(), // literal by handling string escapes.
field.value.constant.length(), &escaped,
true, false);
code_ += " auto* ptr = {{FIELD_VALUE}};"; code_ += " auto* ptr = {{FIELD_VALUE}};";
code_ += " if (ptr) return ptr;"; code_ += " if (ptr) return ptr;";
code_ += " static const struct { uint32_t len; const char s[" + code_ += " static const struct { uint32_t len; const char s[" +
NumToString(field.value.constant.length() + 1) + NumToString(field.value.constant.length() + 1) +
"]; } bfbs_string = { " + "]; } bfbs_string = { " +
NumToString(field.value.constant.length()) + ", " + NumToString(field.value.constant.length()) + ", \"" +
escaped + " };"; field.value.constant + "\" };";
code_ += code_ +=
" return reinterpret_cast<const ::flatbuffers::String " " return reinterpret_cast<const ::flatbuffers::String "
" *>(&bfbs_string);"; " *>(&bfbs_string);";
@@ -3419,15 +3470,11 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("CREATE_STRING", "CreateSharedString"); code_.SetValue("CREATE_STRING", "CreateSharedString");
} }
if (field->value.constant != "0") { if (field->value.constant != "0") {
std::string escaped;
flatbuffers::EscapeString(field->value.constant.c_str(),
field->value.constant.length(), &escaped,
true, false);
code_ += code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : " "_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : "
"_fbb.{{CREATE_STRING}}(" + "_fbb.{{CREATE_STRING}}(\"" +
escaped + ");"; field->value.constant + "\");";
} else { } else {
code_ += code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
@@ -3521,11 +3568,11 @@ class CppGenerator : public BaseGenerator {
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
if (IsStruct(type)) { if (IsStruct(type)) {
const auto& struct_attrs = type.struct_def->attributes; const auto native_type = EffectiveNativeType(afield, *type.struct_def);
const auto native_type = struct_attrs.Lookup("native_type");
if (native_type) { if (native_type) {
std::string unpack_call = "::flatbuffers::UnPack"; std::string unpack_call = "::flatbuffers::UnPack";
const auto pack_name = struct_attrs.Lookup("native_type_pack_name"); const auto pack_name =
EffectiveNativeTypePackName(afield, *type.struct_def);
if (pack_name) { if (pack_name) {
unpack_call += pack_name->constant; unpack_call += pack_name->constant;
} }
@@ -3778,13 +3825,22 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_VECTOR64: case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto vector_type = field.value.type.VectorType(); 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) { switch (vector_type.base_type) {
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
if (NativeString(&field) == "std::string") { if (!custom_vector && NativeString(&field) == "std::string") {
code += "_fbb.CreateVectorOfStrings(" + value + ")"; code += "_fbb.CreateVectorOfStrings(" + value + ")";
} else { } else {
// Use by-function serialization to emulate // Use by-function serialization to emulate
// CreateVectorOfStrings(); this works also with non-std strings. // CreateVectorOfStrings(); this works also with non-std strings
// and non-std::vector vector types.
code += code +=
"_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::" "_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::"
"String>>" "String>>"
@@ -3799,20 +3855,37 @@ class CppGenerator : public BaseGenerator {
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
if (IsStruct(vector_type)) { if (IsStruct(vector_type)) {
const auto& struct_attrs = const auto native_type =
field.value.type.struct_def->attributes; EffectiveNativeType(field, *field.value.type.struct_def);
const auto native_type = struct_attrs.Lookup("native_type");
if (native_type) { if (native_type) {
code += "_fbb.CreateVectorOfNativeStructs<"; code += "_fbb.CreateVectorOfNativeStructs<";
code += WrapInNameSpace(*vector_type.struct_def) + ", " + code += WrapInNameSpace(*vector_type.struct_def) + ", " +
native_type->constant + ">"; native_type->constant + ">";
code += "(" + value; if (custom_vector) {
const auto pack_name = code += "(" + value + ".data(), " + value + ".size()";
struct_attrs.Lookup("native_type_pack_name"); } else {
code += "(" + value;
}
const auto pack_name = EffectiveNativeTypePackName(
field, *field.value.type.struct_def);
if (pack_name) { if (pack_name) {
code += ", ::flatbuffers::Pack" + pack_name->constant; code += ", ::flatbuffers::Pack" + pack_name->constant;
} }
code += ")"; 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 { } else {
// If the field uses 64-bit addressing, create a 64-bit vector. // If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) { if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
@@ -3824,16 +3897,18 @@ class CppGenerator : public BaseGenerator {
code += "64<::flatbuffers::Vector>"; code += "64<::flatbuffers::Vector>";
} }
} }
code += "(" + value + ")"; if (custom_vector) {
code += "(" + value + ".data(), " + value + ".size())";
} else {
code += "(" + value + ")";
}
} }
} else { } else {
code += "_fbb.CreateVector<::flatbuffers::Offset<"; code += "_fbb.CreateVector<::flatbuffers::Offset<";
code += WrapInNameSpace(*vector_type.struct_def) + ">> "; code += WrapInNameSpace(*vector_type.struct_def) + ">> ";
code += "(" + value + ".size(), "; code += "(" + value + ".size(), ";
code += "[](size_t i, _VectorArgs *__va) { "; code += "[](size_t i, _VectorArgs *__va) { ";
code += "return " + code += "return Create" + vector_type.struct_def->name;
WrapInNameSpace(vector_type.struct_def->defined_namespace,
"Create" + vector_type.struct_def->name);
code += "(*__va->__fbb, "; code += "(*__va->__fbb, ";
if (field.native_inline) { if (field.native_inline) {
code += "&(__va->_" + value + "[i])"; code += "&(__va->_" + value + "[i])";
@@ -3845,7 +3920,17 @@ class CppGenerator : public BaseGenerator {
break; break;
} }
case BASE_TYPE_BOOL: { case BASE_TYPE_BOOL: {
code += "_fbb.CreateVector(" + value + ")"; 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 + ")";
}
break; break;
} }
case BASE_TYPE_UNION: { case BASE_TYPE_UNION: {
@@ -3881,9 +3966,11 @@ class CppGenerator : public BaseGenerator {
// the underlying storage type (eg. uint8_t). // the underlying storage type (eg. uint8_t).
const auto basetype = GenTypeBasic( const auto basetype = GenTypeBasic(
field.value.type.enum_def->underlying_type, false); field.value.type.enum_def->underlying_type, false);
code += "_fbb.CreateVectorScalarCast<" + basetype + const std::string data_ptr =
">(::flatbuffers::data(" + value + "), " + value + custom_vector ? value + ".data()"
".size())"; : "::flatbuffers::data(" + value + ")";
code += "_fbb.CreateVectorScalarCast<" + basetype + ">(" +
data_ptr + ", " + value + ".size())";
} else if (field.attributes.Lookup("cpp_type")) { } else if (field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(vector_type, false); auto type = GenTypeBasic(vector_type, false);
code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), "; code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
@@ -3892,6 +3979,27 @@ class CppGenerator : public BaseGenerator {
code += "static_cast<" + type + ">((*__va->__rehasher)"; code += "static_cast<" + type + ">((*__va->__rehasher)";
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0"; code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
code += "; }, &_va )"; 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 { } else {
// If the field uses 64-bit addressing, create a 64-bit vector. // If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) { if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
@@ -3925,12 +4033,12 @@ class CppGenerator : public BaseGenerator {
} }
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
if (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
const auto& struct_attribs = field.value.type.struct_def->attributes; const auto native_type =
const auto native_type = struct_attribs.Lookup("native_type"); EffectiveNativeType(field, *field.value.type.struct_def);
if (native_type && field.native_inline) { if (native_type && field.native_inline) {
code += "::flatbuffers::Pack"; code += "::flatbuffers::Pack";
const auto pack_name = const auto pack_name =
struct_attribs.Lookup("native_type_pack_name"); EffectiveNativeTypePackName(field, *field.value.type.struct_def);
if (pack_name) { if (pack_name) {
code += pack_name->constant; code += pack_name->constant;
} }
@@ -3946,10 +4054,8 @@ class CppGenerator : public BaseGenerator {
} }
} else { } else {
// _o->field ? CreateT(_fbb, _o->field.get(), _rehasher); // _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
const auto& nested_struct = *field.value.type.struct_def; const std::string& type = field.value.type.struct_def->name;
code += value + " ? " + code += value + " ? Create" + type;
WrapInNameSpace(nested_struct.defined_namespace,
"Create" + nested_struct.name);
code += "(_fbb, " + value; code += "(_fbb, " + value;
if (!field.native_inline) code += GenPtrGet(field); if (!field.native_inline) code += GenPtrGet(field);
code += ", _rehasher) : 0"; code += ", _rehasher) : 0";
@@ -4097,8 +4203,7 @@ class CppGenerator : public BaseGenerator {
if (field->value.type.base_type == BASE_TYPE_STRUCT) { if (field->value.type.base_type == BASE_TYPE_STRUCT) {
if (IsStruct(field->value.type)) { if (IsStruct(field->value.type)) {
auto native_type = auto native_type =
field->value.type.struct_def->attributes.Lookup( EffectiveNativeType(*field, *field->value.type.struct_def);
"native_type");
auto native_inline = field->attributes.Lookup("native_inline"); auto native_inline = field->attributes.Lookup("native_inline");
if (native_type) { if (native_type) {
pass_by_address = true; pass_by_address = true;
@@ -4453,6 +4558,141 @@ 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 // Set up the correct namespace. Only open a namespace if the existing one is
// different (closing/opening only what is necessary). // different (closing/opening only what is necessary).
// //
+25 -6
View File
@@ -654,15 +654,34 @@ class DartGenerator : public BaseGenerator {
std::string NamespaceAliasFromUnionType(Namespace* root_namespace, std::string NamespaceAliasFromUnionType(Namespace* root_namespace,
const Type& type) { const Type& type) {
const Namespace& type_namespace = *type.struct_def->defined_namespace; const std::vector<std::string> qualified_name_parts =
if (root_namespace->components == type_namespace.components) { type.struct_def->defined_namespace->components;
if (std::equal(root_namespace->components.begin(),
root_namespace->components.end(),
qualified_name_parts.begin())) {
return namer_.Type(*type.struct_def); return namer_.Type(*type.struct_def);
} }
const std::string ns = namer_.Namespace(type_namespace); std::string ns;
return ns.empty()
? namer_.Type(*type.struct_def) for (auto it = qualified_name_parts.begin();
: ImportAliasName(ns) + "." + namer_.Type(*type.struct_def); 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);
} }
void GenImplementationGetters( void GenImplementationGetters(
+1 -11
View File
@@ -368,17 +368,7 @@ static std::string GenerateFBS(const Parser& parser,
if (field.value.type.base_type != BASE_TYPE_UTYPE) { if (field.value.type.base_type != BASE_TYPE_UTYPE) {
GenComment(field.doc_comment, &schema, nullptr, " "); GenComment(field.doc_comment, &schema, nullptr, " ");
schema += " " + field.name + ":" + GenType(field.value.type); schema += " " + field.name + ":" + GenType(field.value.type);
if (field.value.constant != "0") { if (field.value.constant != "0") schema += " = " + field.value.constant;
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; std::vector<std::string> attributes;
if (field.IsRequired()) attributes.push_back("required"); if (field.IsRequired()) attributes.push_back("required");
if (field.key) attributes.push_back("key"); if (field.key) attributes.push_back("key");
+5 -5
View File
@@ -1528,7 +1528,7 @@ class PythonGenerator : public BaseGenerator {
} else { } else {
code += "def Create" + field_method + "Vector(builder, data):\n"; code += "def Create" + field_method + "Vector(builder, data):\n";
} }
code += Indent + "return " + helper_name + "(builder, data)\n\n"; code += Indent + helper_name + "(builder, data)\n\n";
} }
} }
@@ -2095,12 +2095,12 @@ class PythonGenerator : public BaseGenerator {
const auto field_method = namer_.Method(field); const auto field_method = namer_.Method(field);
const auto struct_var = namer_.Variable(struct_def); const auto struct_var = namer_.Variable(struct_def);
const EnumDef& enum_def = *field.value.type.enum_def; const EnumDef& enum_def = *field.value.type.enum_def;
auto union_fn = namer_.Function(enum_def); auto union_type = namer_.Type(enum_def);
if (parser_.opts.include_dependence_headers) { if (parser_.opts.include_dependence_headers) {
union_fn = namer_.NamespacedType(enum_def) + "." + union_fn; union_type = namer_.NamespacedType(enum_def) + "." + union_type;
} }
code += GenIndents(2) + "self." + field_field + " = " + union_fn + code += GenIndents(2) + "self." + field_field + " = " + union_type +
"Creator(" + "self." + field_field + "Type, " + struct_var + "." + "Creator(" + "self." + field_field + "Type, " + struct_var + "." +
field_method + "())"; field_method + "())";
} }
@@ -2471,7 +2471,7 @@ class PythonGenerator : public BaseGenerator {
} else { } else {
GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3); GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
code_prefix += "(self." + field_field + "[i])"; code_prefix += "(self." + field_field + "[i])";
code_prefix += GenIndents(3) + field_field + " = builder.EndVector()"; code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
} }
} }
+414 -552
View File
File diff suppressed because it is too large Load Diff
+49 -83
View File
@@ -164,14 +164,15 @@ class SwiftGenerator : public BaseGenerator {
bool generate() { bool generate() {
code_.Clear(); code_.Clear();
code_.SetValue("ACCESS", "_accessor"); code_.SetValue("ACCESS", "_accessor");
code_.SetValue("TABLEOFFSET", "VT"); code_.SetValue("TABLEOFFSET", "VTOFFSET");
code_ += "// " + std::string(FlatBuffersGeneratedWarning()); code_ += "// " + std::string(FlatBuffersGeneratedWarning());
code_ += "// swiftlint:disable all"; code_ += "// swiftlint:disable all";
code_ += "// swiftformat:disable all\n"; code_ += "// swiftformat:disable all\n";
if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) { if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
code_.SetValue("IMPLEMENTONLY", code_.SetValue("IMPLEMENTONLY", parser_.opts.swift_implementation_only
parser_.opts.swift_implementation_only ? "internal " : ""); ? "@_implementationOnly "
: "");
code_ += "#if canImport(Common)"; code_ += "#if canImport(Common)";
code_ += "{{IMPLEMENTONLY}}import Common"; code_ += "{{IMPLEMENTONLY}}import Common";
code_ += "#endif"; code_ += "#endif";
@@ -281,16 +282,9 @@ class SwiftGenerator : public BaseGenerator {
NumToString(field.value.type.VectorType().fixed_length); NumToString(field.value.type.VectorType().fixed_length);
code_.SetValue("FIXEDLENGTH", fixed_length); code_.SetValue("FIXEDLENGTH", fixed_length);
std::string vector_base_type; const auto vector_base_type = IsStruct(field.value.type.VectorType())
if (IsStruct(field.value.type.VectorType())) { ? (type + "()")
vector_base_type = type + "()"; : SwiftConstant(field);
} 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}}, " + code_ += "private var _{{FIELDVAR}}: InlineArray<{{FIXEDLENGTH}}, " +
valueType + ">"; valueType + ">";
@@ -524,7 +518,7 @@ class SwiftGenerator : public BaseGenerator {
void GenTableAccessors(const StructDef& struct_def) { void GenTableAccessors(const StructDef& struct_def) {
// Generate field id constants. // Generate field id constants.
if (struct_def.fields.vec.size() > 0) { if (struct_def.fields.vec.size() > 0) {
code_ += "private struct {{TABLEOFFSET}} {"; code_ += "private enum {{TABLEOFFSET}}: VOffset {";
Indent(); Indent();
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
@@ -534,8 +528,10 @@ class SwiftGenerator : public BaseGenerator {
} }
code_.SetValue("OFFSET_NAME", namer_.Variable(field)); code_.SetValue("OFFSET_NAME", namer_.Variable(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset)); code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
code_ += "static let {{OFFSET_NAME}}: VOffset = {{OFFSET_VALUE}}"; code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
} }
code_ += "var v: Int32 { Int32(self.rawValue) }";
code_ += "var p: VOffset { self.rawValue }";
Outdent(); Outdent();
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
@@ -548,14 +544,13 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("SHORT_STRUCTNAME", namer_.Type(struct_def)); code_.SetValue("SHORT_STRUCTNAME", namer_.Type(struct_def));
code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def)); code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table"); code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
code_.SetValue("PROTOCOL", struct_def.fixed ? "FlatBufferStruct"
: "FlatBufferVerifiableTable");
code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : ""); code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
GenOSVersionChecks(); GenOSVersionChecks();
code_ += code_ +=
"{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: " "{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: "
"{{PROTOCOL}}, FlatbuffersVectorInitializable\\"; "FlatBuffer{{OBJECTTYPE}}, FlatbuffersVectorInitializable\\";
if (!struct_def.fixed) code_ += ", Verifiable\\";
if (!struct_def.fixed && parser_.opts.generate_object_based_api) if (!struct_def.fixed && parser_.opts.generate_object_based_api)
code_ += ", ObjectAPIPacker\\"; code_ += ", ObjectAPIPacker\\";
code_ += " {\n"; code_ += " {\n";
@@ -625,8 +620,7 @@ class SwiftGenerator : public BaseGenerator {
if (should_generate_create) { if (should_generate_create) {
code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}("; code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(";
Indent(); 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(); for (auto it = create_func_header.begin(); it < create_func_header.end();
++it) { ++it) {
code_ += *it + "\\"; code_ += *it + "\\";
@@ -705,7 +699,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += field.IsOptional() ? (optional_enum + "\\") code_ += field.IsOptional() ? (optional_enum + "\\")
: (is_enum + ", def: {{CONSTANT}}\\"); : (is_enum + ", def: {{CONSTANT}}\\");
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}) }"; code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
const auto default_value = const auto default_value =
IsEnum(field.value.type) IsEnum(field.value.type)
@@ -725,7 +719,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += code_ +=
"{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\"; "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\";
code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},"; code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}) }"; code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back( create_func_header.push_back(
field_var + ": " + nullable_type + " = " + field_var + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value)); (field.IsOptional() ? "nil" : default_value));
@@ -736,7 +730,7 @@ class SwiftGenerator : public BaseGenerator {
const auto create_struct = const auto create_struct =
"guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };" "guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };"
" fbb.create(struct: {{FIELDVAR}}, position: " " fbb.create(struct: {{FIELDVAR}}, position: "
"{{TABLEOFFSET}}.{{OFFSET}}) }"; "{{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += type + "?" + builder_string + create_struct; code_ += type + "?" + builder_string + create_struct;
/// Optional hard coded since structs are always optional /// Optional hard coded since structs are always optional
create_func_header.push_back(field_var + ": " + type + create_func_header.push_back(field_var + ": " + type +
@@ -753,9 +747,8 @@ class SwiftGenerator : public BaseGenerator {
(field.IsRequired() ? "" : " = Offset()")); (field.IsRequired() ? "" : " = Offset()"));
const auto reader_type = const auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}) }" ? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
: "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}) " : "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
"}";
code_ += "Offset" + builder_string + "fbb.add(" + reader_type; code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
const auto vectortype = field.value.type.VectorType(); const auto vectortype = field.value.type.VectorType();
@@ -859,10 +852,7 @@ class SwiftGenerator : public BaseGenerator {
break; break;
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
const auto sc = SwiftConstant(field); const auto default_string = "\"" + 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("VALUETYPE", GenType(field.value.type));
code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil"); code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() + code_ += GenReaderMainBody(is_required) + GenOffset() +
@@ -870,7 +860,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" + code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" +
is_required + is_required +
" { return " " { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}) }"; "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
break; break;
} }
case BASE_TYPE_ARRAY: case BASE_TYPE_ARRAY:
@@ -904,7 +894,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: " "{{ACCESS_TYPE}} var {{FIELDVAR}}: "
"FlatbufferVector<{{VALUETYPE}}> " "FlatbufferVector<{{VALUETYPE}}> "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}, " "{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"byteSize: {{SIZE}}) }"; "byteSize: {{SIZE}}) }";
} }
@@ -921,7 +911,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: " "{{ACCESS_TYPE}} var {{FIELDVAR}}: "
"FlatbufferVector<{{VALUETYPE}}_Mutable> " "FlatbufferVector<{{VALUETYPE}}_Mutable> "
"{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}, " "{ return {{ACCESS}}.vector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"byteSize: {{SIZE}}) }"; "byteSize: {{SIZE}}) }";
GenUnsafeBufferPointer(field); GenUnsafeBufferPointer(field);
return; return;
@@ -930,8 +920,7 @@ class SwiftGenerator : public BaseGenerator {
if (vectortype.base_type == BASE_TYPE_UNION) { if (vectortype.base_type == BASE_TYPE_UNION) {
code_ += code_ +=
"{{ACCESS_TYPE}} var {{FIELDVAR}}: UnionFlatbufferVector " "{{ACCESS_TYPE}} var {{FIELDVAR}}: UnionFlatbufferVector "
"{ return {{ACCESS}}.unionVector(at: " "{ return {{ACCESS}}.unionVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{{TABLEOFFSET}}.{{OFFSET}}, "
"byteSize: {{SIZE}}) }"; "byteSize: {{SIZE}}) }";
code_ += code_ +=
"{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at " "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at "
@@ -965,21 +954,24 @@ class SwiftGenerator : public BaseGenerator {
"{{ACCESS_TYPE}} func {{functionName}}<T>(_ body: " "{{ACCESS_TYPE}} func {{functionName}}<T>(_ body: "
"(UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return " "(UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? { return "
"try " "try "
"{{ACCESS}}.withUnsafePointerToSlice(at: " "{{ACCESS}}.withUnsafePointerToSlice(at: {{TABLEOFFSET}}.{{OFFSET}}.v, "
"{{TABLEOFFSET}}.{{OFFSET}}, "
"body: body) }"; "body: body) }";
} }
std::vector<std::string> GenerateCodingKeys(const StructDef& struct_def) { void GenerateCodingKeys(const StructDef& struct_def) {
std::vector<std::string> coding_keys; code_ += "enum CodingKeys: String, CodingKey {";
Indent();
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
const auto& field = **it; const auto& field = **it;
if (field.deprecated) continue; if (field.deprecated) continue;
coding_keys.push_back("case " + namer_.Variable(field) + " = \"" +
field.name + "\""); code_.SetValue("RAWVALUENAME", field.name);
code_.SetValue("FIELDVAR", namer_.Variable(field));
code_ += "case {{FIELDVAR}} = \"{{RAWVALUENAME}}\"";
} }
return coding_keys; Outdent();
code_ += "}";
} }
void GenerateEncoderUnionBody(const FieldDef& field) { void GenerateEncoderUnionBody(const FieldDef& field) {
@@ -1101,31 +1093,14 @@ class SwiftGenerator : public BaseGenerator {
GenOSVersionChecks(); GenOSVersionChecks();
code_ += "extension {{STRUCTNAME}}: Encodable {"; code_ += "extension {{STRUCTNAME}}: Encodable {";
Indent(); Indent();
auto coding_keys = GenerateCodingKeys(struct_def); code_ += "";
if (struct_def.fields.vec.empty() == false) 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 {"; code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
Indent();
if (coding_keys.empty() == false) { if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
Indent(); Outdent();
GenerateEncoderBody(struct_def);
Outdent();
}
code_ += "}"; code_ += "}";
Outdent(); Outdent();
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
@@ -1155,7 +1130,7 @@ class SwiftGenerator : public BaseGenerator {
} }
code_ += code_ +=
"try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}, fieldName: " "try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
"\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: " "\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: "
"{{VALUETYPE}}.self)"; "{{VALUETYPE}}.self)";
} }
@@ -1175,9 +1150,8 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def)); code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def));
code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit"); code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
code_ += code_ +=
"try _v.{{FUNCTION_NAME}}(unionKey: " "try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
"{{TABLEOFFSET}}.{{OFFSET}}Type, " "unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
"unionField: {{TABLEOFFSET}}.{{OFFSET}}, unionKeyName: "
"\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: " "\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: "
"{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in"; "{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
Indent(); Indent();
@@ -1652,23 +1626,15 @@ class SwiftGenerator : public BaseGenerator {
buffer_constructor.push_back(field_var + " = _t." + field_field); buffer_constructor.push_back(field_var + " = _t." + field_field);
if (field.IsRequired()) { if (field.IsRequired()) {
std::string default_value; std::string default_value =
if (field.IsDefault()) { field.IsDefault() ? SwiftConstant(field) : "";
const auto sc = SwiftConstant(field); base_constructor.push_back(field_var + " = \"" + default_value +
flatbuffers::EscapeString(sc.c_str(), sc.length(), &default_value, "\"");
true, false);
} else {
default_value = "\"\"";
}
base_constructor.push_back(field_var + " = " + default_value);
break; break;
} }
if (field.IsDefault() && !field.IsRequired()) { if (field.IsDefault() && !field.IsRequired()) {
const auto sc = SwiftConstant(field); std::string value = field.IsDefault() ? SwiftConstant(field) : "nil";
std::string value; base_constructor.push_back(field_var + " = \"" + value + "\"");
flatbuffers::EscapeString(sc.c_str(), sc.length(), &value,
true, false);
base_constructor.push_back(field_var + " = " + value);
} }
break; break;
} }
@@ -1927,7 +1893,7 @@ class SwiftGenerator : public BaseGenerator {
} }
std::string GenOffset() { std::string GenOffset() {
return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}); "; return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
} }
std::string GenReaderMainBody(const std::string& optional = "") { std::string GenReaderMainBody(const std::string& optional = "") {
+53 -169
View File
@@ -324,10 +324,9 @@ class TsGenerator : public BaseGenerator {
export_counter++; export_counter++;
} }
if (export_counter > 0) { if (export_counter > 0)
parser_.opts.file_saver->SaveFile(it.second.filepath.c_str(), code, parser_.opts.file_saver->SaveFile(it.second.filepath.c_str(), code,
false); false);
}
} }
} }
@@ -522,20 +521,7 @@ class TsGenerator : public BaseGenerator {
case BASE_TYPE_BOOL: case BASE_TYPE_BOOL:
return value.constant == "0" ? "false" : "true"; 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_UNION:
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
return null_keyword_; return null_keyword_;
@@ -661,8 +647,7 @@ class TsGenerator : public BaseGenerator {
} }
void GenStructArgs(import_set& imports, const StructDef& struct_def, void GenStructArgs(import_set& imports, const StructDef& struct_def,
const Definition& owner, std::string* arguments, std::string* arguments, const std::string& nameprefix) {
const std::string& nameprefix) {
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto& field = **it; auto& field = **it;
@@ -670,11 +655,11 @@ class TsGenerator : public BaseGenerator {
// Generate arguments for a struct inside a struct. To ensure names // Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing // don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name. // a nested struct, prefix the name with the field name.
GenStructArgs(imports, *field.value.type.struct_def, owner, arguments, GenStructArgs(imports, *field.value.type.struct_def, arguments,
nameprefix + field.name + "_"); nameprefix + field.name + "_");
} else { } else {
*arguments += ", " + nameprefix + field.name + ": " + *arguments += ", " + nameprefix + field.name + ": " +
GenTypeName(imports, owner, field.value.type, true, GenTypeName(imports, field, field.value.type, true,
field.IsOptional()); field.IsOptional());
} }
} }
@@ -936,48 +921,6 @@ class TsGenerator : public BaseGenerator {
return symbols_expression; 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> template <typename DefinitionT>
ImportDefinition AddImport(import_set& imports, const Definition& dependent, ImportDefinition AddImport(import_set& imports, const Definition& dependent,
const DefinitionT& dependency) { const DefinitionT& dependency) {
@@ -1005,32 +948,26 @@ class TsGenerator : public BaseGenerator {
const std::string symbols_expression = GenSymbolExpression( const std::string symbols_expression = GenSymbolExpression(
dependency, has_name_clash, import_name, name, object_name); dependency, has_name_clash, import_name, name, object_name);
const Namespace* dependent_ns = dependent.defined_namespace std::string bare_file_path;
? dependent.defined_namespace std::string rel_file_path;
: parser_.empty_namespace_; if (dependent.defined_namespace) {
const Namespace* dependency_ns = dependency.defined_namespace const auto& dep_comps = dependent.defined_namespace->components;
? dependency.defined_namespace for (size_t i = 0; i < dep_comps.size(); i++) {
: parser_.empty_namespace_; rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
}
if (dep_comps.size() == 0) {
rel_file_path += ".";
}
} else {
rel_file_path += "..";
}
const std::string dependent_dirs = bare_file_path +=
namer_.Directories(*dependent_ns, SkipDir::OutputPath); kPathSeparator +
const std::string dependency_dirs = namer_.Directories(dependency.defined_namespace->components,
namer_.Directories(*dependency_ns, SkipDir::OutputPath); 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); namer_.File(dependency, SkipFile::SuffixAndExtension);
rel_file_path += bare_file_path;
ImportDefinition import; ImportDefinition import;
import.name = name; import.name = name;
@@ -1235,10 +1172,9 @@ class TsGenerator : public BaseGenerator {
std::string GenNullCheckConditional(const std::string& nullCheckVar, std::string GenNullCheckConditional(const std::string& nullCheckVar,
const std::string& trueVal, 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 + return "(" + nullCheckVar + " !== " + null_keyword_ + " ? " + trueVal +
" : " + false_val + ")"; " : " + falseVal + ")";
} }
std::string GenStructMemberValueTS(const StructDef& struct_def, std::string GenStructMemberValueTS(const StructDef& struct_def,
@@ -1347,9 +1283,10 @@ class TsGenerator : public BaseGenerator {
// Emit a scalar field // Emit a scalar field
const auto is_string = IsString(field.value.type); const auto is_string = IsString(field.value.type);
if (IsScalar(field.value.type.base_type) || is_string) { if (IsScalar(field.value.type.base_type) || is_string) {
field_type += const auto has_null_default = is_string || HasNullDefault(field);
GenTypeName(imports, field, field.value.type, false,
!HasDefaultValue(field) || HasNullDefault(field)); field_type += GenTypeName(imports, field, field.value.type, false,
has_null_default);
field_val = "this." + namer_.Method(field) + "()"; field_val = "this." + namer_.Method(field) + "()";
if (field.value.type.base_type != BASE_TYPE_STRING) { if (field.value.type.base_type != BASE_TYPE_STRING) {
@@ -1695,12 +1632,11 @@ class TsGenerator : public BaseGenerator {
GenDocComment(struct_def.doc_comment, code_ptr); GenDocComment(struct_def.doc_comment, code_ptr);
code += "export class "; code += "export class ";
code += object_name; code += object_name;
if (parser.opts.generate_object_based_api) { if (parser.opts.generate_object_based_api)
code += " implements flatbuffers.IUnpackableObject<" + object_api_name + code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
"> {\n"; "> {\n";
} else { else
code += " {\n"; code += " {\n";
}
code += " bb: flatbuffers.ByteBuffer|" + null_keyword_ + " = " + code += " bb: flatbuffers.ByteBuffer|" + null_keyword_ + " = " +
null_keyword_ + ";\n"; null_keyword_ + ";\n";
code += " bb_pos = 0;\n"; code += " bb_pos = 0;\n";
@@ -1743,22 +1679,21 @@ class TsGenerator : public BaseGenerator {
offset_prefix = " const offset = " + GenBBAccess() + offset_prefix = " const offset = " + GenBBAccess() +
".__offset(this.bb_pos, " + ".__offset(this.bb_pos, " +
NumToString(field.value.offset) + ");\n"; NumToString(field.value.offset) + ");\n";
offset_prefix += " return "; offset_prefix += " return offset ? ";
} }
// Emit a scalar field // Emit a scalar field
const auto is_string = IsString(field.value.type); const auto is_string = IsString(field.value.type);
if (IsScalar(field.value.type.base_type) || is_string) { if (IsScalar(field.value.type.base_type) || is_string) {
const auto has_null_default = const auto has_null_default = is_string || HasNullDefault(field);
!field.IsRequired() && !HasDefaultValue(field);
GenDocComment(field.doc_comment, code_ptr); GenDocComment(field.doc_comment, code_ptr);
std::string prefix = namer_.Method(field) + "("; std::string prefix = namer_.Method(field) + "(";
if (is_string) { if (is_string) {
code += prefix + "):" + (has_null_default ? "string|" + null_keyword_ : "string") + "\n"; code += prefix + "):string|" + null_keyword_ + "\n";
code += code +=
prefix + "optionalEncoding:flatbuffers.Encoding" + "):" + prefix + "optionalEncoding:flatbuffers.Encoding" + "):" +
GenTypeName(imports, struct_def, field.value.type, false, has_null_default) + GenTypeName(imports, struct_def, field.value.type, false, true) +
"\n"; "\n";
code += prefix + "optionalEncoding?:any"; code += prefix + "optionalEncoding?:any";
} else { } else {
@@ -1787,16 +1722,9 @@ class TsGenerator : public BaseGenerator {
if (is_string) { if (is_string) {
index += ", optionalEncoding"; index += ", optionalEncoding";
} }
if (field.IsRequired()) { code +=
code += offset_prefix + GenGetter(field.value.type, "(" + index + ")");
offset_prefix + GenGetter(field.value.type, "(" + index + ")"); if (field.value.type.base_type != BASE_TYPE_ARRAY) {
;
} 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 += " : " + GenDefaultValue(field, imports);
} }
code += ";\n"; code += ";\n";
@@ -1821,8 +1749,8 @@ class TsGenerator : public BaseGenerator {
code += code +=
MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n"; MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n";
} else { } else {
code += offset_prefix + "offset ? (obj || " + code += offset_prefix + "(obj || " + GenerateNewExpression(type) +
GenerateNewExpression(type) + ").__init("; ").__init(";
code += field.value.type.struct_def->fixed code += field.value.type.struct_def->fixed
? "this.bb_pos + offset" ? "this.bb_pos + offset"
: GenBBAccess() + ".__indirect(this.bb_pos + offset)"; : GenBBAccess() + ".__indirect(this.bb_pos + offset)";
@@ -1980,7 +1908,7 @@ class TsGenerator : public BaseGenerator {
code += "):" + vectortypename + "|" + null_keyword_ + " {\n"; code += "):" + vectortypename + "|" + null_keyword_ + " {\n";
if (vectortype.base_type == BASE_TYPE_STRUCT) { if (vectortype.base_type == BASE_TYPE_STRUCT) {
code += offset_prefix + "offset ? (obj || " + code += offset_prefix + "(obj || " +
GenerateNewExpression(vectortypename); GenerateNewExpression(vectortypename);
code += ").__init("; code += ").__init(";
code += vectortype.struct_def->fixed code += vectortype.struct_def->fixed
@@ -1993,8 +1921,7 @@ class TsGenerator : public BaseGenerator {
} else if (IsString(vectortype)) { } else if (IsString(vectortype)) {
index += ", optionalEncoding"; index += ", optionalEncoding";
} }
code += offset_prefix + "offset ? " + code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
GenGetter(vectortype, "(" + index + ")");
} }
code += " : "; code += " : ";
if (field.value.type.element == BASE_TYPE_BOOL) { if (field.value.type.element == BASE_TYPE_BOOL) {
@@ -2026,7 +1953,7 @@ class TsGenerator : public BaseGenerator {
" " " "
"{\n"; "{\n";
code += offset_prefix + "offset ? " + code += offset_prefix +
GenGetter(field.value.type, "(obj, this.bb_pos + offset)") + GenGetter(field.value.type, "(obj, this.bb_pos + offset)") +
" : " + null_keyword_ + ";\n"; " : " + null_keyword_ + ";\n";
break; break;
@@ -2079,7 +2006,7 @@ class TsGenerator : public BaseGenerator {
// Emit a length helper // Emit a length helper
GenDocComment(code_ptr); GenDocComment(code_ptr);
code += namer_.Method(field, "Length"); code += namer_.Method(field, "Length");
code += "():number {\n" + offset_prefix + "offset ? "; code += "():number {\n" + offset_prefix;
code += code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n"; GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
@@ -2090,30 +2017,15 @@ class TsGenerator : public BaseGenerator {
GenDocComment(code_ptr); GenDocComment(code_ptr);
code += namer_.Method(field, "Array"); code += namer_.Method(field, "Array");
code += "():" + GenType(vectorType) + "Array|" + null_keyword_ +
" {\n" + offset_prefix;
std::string return_type = code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
(field.IsRequired() || HasDefaultValue(field)) ".bytes().buffer, " + GenBBAccess() +
? "Array" ".bytes().byteOffset + " + GenBBAccess() +
: ("Array|" + null_keyword_); ".__vector(this.bb_pos + offset), " + GenBBAccess() +
if (field.IsRequired()) { ".__vector_len(this.bb_pos + offset)) : " + null_keyword_ +
code += "():" + GenType(vectorType) + return_type + " {\n" + ";\n}\n\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";
}
} }
} }
} }
@@ -2142,7 +2054,7 @@ class TsGenerator : public BaseGenerator {
// Emit a factory constructor // Emit a factory constructor
if (struct_def.fixed) { if (struct_def.fixed) {
std::string arguments; std::string arguments;
GenStructArgs(imports, struct_def, struct_def, &arguments, ""); GenStructArgs(imports, struct_def, &arguments, "");
GenDocComment(code_ptr); GenDocComment(code_ptr);
code += "static create" + GetPrefixedName(struct_def) + code += "static create" + GetPrefixedName(struct_def) +
@@ -2344,34 +2256,6 @@ class TsGenerator : public BaseGenerator {
return field.IsOptional() && field.value.constant == "null"; 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, std::string GetArgType(import_set& imports, const Definition& owner,
const FieldDef& field, bool allowNull) { const FieldDef& field, bool allowNull) {
return GenTypeName(imports, owner, field.value.type, true, return GenTypeName(imports, owner, field.value.type, true,
+53 -15
View File
@@ -1286,6 +1286,55 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
"'native_inline' can only be defined on structs, vector of structs or " "'native_inline' can only be defined on structs, vector of structs or "
"vector of tables"); "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"); auto nested = field->attributes.Lookup("nested_flatbuffer");
if (nested) { if (nested) {
if (nested->type.base_type != BASE_TYPE_STRING) if (nested->type.base_type != BASE_TYPE_STRING)
@@ -2809,8 +2858,7 @@ bool Parser::SupportsOptionalScalars() const {
bool Parser::SupportsDefaultVectorsAndStrings() const { bool Parser::SupportsDefaultVectorsAndStrings() const {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim | 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); return !(opts.lang_to_generate & ~supported_langs);
} }
@@ -3172,10 +3220,8 @@ CheckedError Parser::ParseProtoFields(StructDef* struct_def, bool isextend,
return Error("Protobuf has non positive number in reserved ids"); return Error("Protobuf has non positive number in reserved ids");
if (range) { if (range) {
for (uint32_t id = static_cast<uint32_t>(from) + 1; for (voffset_t id = from + 1; id <= attribute; id++)
id <= static_cast<uint32_t>(attribute); id++) { struct_def->reserved_ids.push_back(id);
struct_def->reserved_ids.push_back(static_cast<voffset_t>(id));
}
range = false; range = false;
} else { } else {
@@ -4132,15 +4178,7 @@ bool StructDef::Deserialize(Parser& parser, const reflection::Object* object) {
sortbysize = attributes.Lookup("original_order") == nullptr && !fixed; sortbysize = attributes.Lookup("original_order") == nullptr && !fixed;
const auto& of = *(object->fields()); const auto& of = *(object->fields());
auto indexes = std::vector<uoffset_t>(of.size()); auto indexes = std::vector<uoffset_t>(of.size());
for (uoffset_t i = 0; i < of.size(); i++) { for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = 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; size_t tmp_struct_size = 0;
for (size_t i = 0; i < indexes.size(); i++) { for (size_t i = 0; i < indexes.size(); i++) {
auto field = of.Get(indexes[i]); auto field = of.Get(indexes[i]);
+2 -5
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) { for (size_t i = 0; i < field_to_id_map.size(); ++i) {
func(object->fields()->Get( 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,10 +641,7 @@ const uint8_t* AddFlatBuffer(std::vector<uint8_t>& flatbuf,
const uint8_t* newbuf, size_t newlen) { const uint8_t* newbuf, size_t newlen) {
// Align to sizeof(uoffset_t) past sizeof(largest_scalar_t) since we're // Align to sizeof(uoffset_t) past sizeof(largest_scalar_t) since we're
// going to chop off the root offset. // going to chop off the root offset.
if (!newbuf || newlen < sizeof(uoffset_t)) return nullptr;
FLATBUFFERS_ASSERT(newlen >= sizeof(uoffset_t)); 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)) || while ((flatbuf.size() & (sizeof(uoffset_t) - 1)) ||
!(flatbuf.size() & (sizeof(largest_scalar_t) - 1))) { !(flatbuf.size() & (sizeof(largest_scalar_t) - 1))) {
flatbuf.push_back(0); flatbuf.push_back(0);
@@ -652,7 +649,7 @@ const uint8_t* AddFlatBuffer(std::vector<uint8_t>& flatbuf,
auto insertion_point = static_cast<uoffset_t>(flatbuf.size()); auto insertion_point = static_cast<uoffset_t>(flatbuf.size());
// Insert the entire FlatBuffer minus the root pointer. // Insert the entire FlatBuffer minus the root pointer.
flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen); flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen);
auto root_offset = root - sizeof(uoffset_t); auto root_offset = ReadScalar<uoffset_t>(newbuf) - sizeof(uoffset_t);
return flatbuf.data() + insertion_point + root_offset; 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 /// 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. /// 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, BitwiseCopyable { public protocol Scalar: Equatable {
associatedtype NumericValue associatedtype NumericValue
var convertedEndian: NumericValue { get } var convertedEndian: NumericValue { get }
} }
+11 -48
View File
@@ -20,56 +20,22 @@ import Foundation
/// it allows users to write and read data directly from memory thus the use of its /// it allows users to write and read data directly from memory thus the use of its
/// functions should be used /// functions should be used
@frozen @frozen
public struct ByteBuffer: @unchecked Sendable { public struct ByteBuffer {
/// Storage is a container that would hold the memory pointer to solve the issue of /// Storage is a container that would hold the memory pointer to solve the issue of
/// deallocating the memory that was held by (memory: UnsafeMutableRawPointer) /// deallocating the memory that was held by (memory: UnsafeMutableRawPointer)
@usableFromInline @usableFromInline
final class Storage { final class Storage {
@usableFromInline @usableFromInline
@frozen enum Blob: ~Copyable { enum Blob {
#if !os(WASI) #if !os(WASI)
case data(Data) case data(Data)
case bytes(any ContiguousBytes) case bytes(ContiguousBytes)
#endif #endif
case byteBuffer(_InternalByteBuffer) case byteBuffer(_InternalByteBuffer)
case array([UInt8]) case array([UInt8])
case pointer(UnsafeMutableRawPointer) 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. /// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -78,7 +44,7 @@ public struct ByteBuffer: @unchecked Sendable {
private let capacity: Int private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to. /// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline @usableFromInline
let retainedBlob: Blob var retainedBlob: Blob
@usableFromInline @usableFromInline
init(count: Int) { init(count: Int) {
@@ -91,9 +57,9 @@ public struct ByteBuffer: @unchecked Sendable {
} }
@usableFromInline @usableFromInline
init(blob: borrowing Blob, capacity count: Int) { init(blob: Blob, capacity count: Int) {
capacity = count capacity = count
retainedBlob = .init(blob) retainedBlob = blob
isOwned = false isOwned = false
} }
@@ -184,7 +150,6 @@ public struct ByteBuffer: @unchecked Sendable {
@discardableResult @discardableResult
@inline(__always) @inline(__always)
@inlinable
func readWithUnsafeRawPointer<T>( func readWithUnsafeRawPointer<T>(
position: Int, position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T _ body: (UnsafeRawPointer) throws -> T) rethrows -> T
@@ -313,7 +278,7 @@ public struct ByteBuffer: @unchecked Sendable {
/// - removeBytes: Removes a number of bytes from the current size /// - removeBytes: Removes a number of bytes from the current size
@inline(__always) @inline(__always)
init( init(
blob: borrowing Storage.Blob, blob: Storage.Blob,
count: Int, count: Int,
removing removeBytes: Int) removing removeBytes: Int)
{ {
@@ -353,8 +318,7 @@ public struct ByteBuffer: @unchecked Sendable {
/// - def: Type of the object /// - def: Type of the object
/// - position: the index of the object in the buffer /// - position: the index of the object in the buffer
@inline(__always) @inline(__always)
@inlinable 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) { _storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1) $0.bindMemory(to: T.self, capacity: 1)
.pointee .pointee
@@ -448,7 +412,7 @@ public struct ByteBuffer: @unchecked Sendable {
/// - Parameter removeBytes: the amount of bytes to remove from the current Size /// - Parameter removeBytes: the amount of bytes to remove from the current Size
@inline(__always) @inline(__always)
public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer { 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( assert(
removeBytes < capacity, removeBytes < capacity,
"Can NOT remove more bytes than the ones allocated") "Can NOT remove more bytes than the ones allocated")
@@ -500,9 +464,8 @@ public struct ByteBuffer: @unchecked Sendable {
extension ByteBuffer: CustomDebugStringConvertible { extension ByteBuffer: CustomDebugStringConvertible {
public var debugDescription: String { public var debugDescription: String {
let blobDescription = _storage.retainedBlob.description """
return """ buffer located at: \(_storage.retainedBlob),
buffer located at: \(blobDescription),
with capacity of \(capacity), with capacity of \(capacity),
{ writtenSize: \(_readerIndex), readerSize: \(reader), { writtenSize: \(_readerIndex), readerSize: \(reader),
size: \(size) } size: \(size) }
+1 -1
View File
@@ -23,7 +23,7 @@ import Common
/// Enum is a protocol that all flatbuffers enums should conform to /// Enum is a protocol that all flatbuffers enums should conform to
/// Since it allows us to get the actual `ByteSize` and `Value` from /// Since it allows us to get the actual `ByteSize` and `Value` from
/// a swift enum. /// a swift enum.
public protocol Enum: Sendable { public protocol Enum {
/// associatedtype that the type of the enum should conform to /// associatedtype that the type of the enum should conform to
associatedtype T: Scalar & Verifiable associatedtype T: Scalar & Verifiable
/// Size of the current associatedtype in the enum /// Size of the current associatedtype in the enum
@@ -45,10 +45,9 @@ public struct FlatBufferBuilder {
/// Dictonary that stores a map of all the strings that were written to the buffer /// Dictonary that stores a map of all the strings that were written to the buffer
private var stringOffsetMap: [String: Offset] = [:] private var stringOffsetMap: [String: Offset] = [:]
/// A check to see if finish(::) was ever called to retreive data object /// A check to see if finish(::) was ever called to retreive data object
private(set) var finished = false private var finished = false
/// A check to see if the buffer should serialize Default values /// A check to see if the buffer should serialize Default values
@usableFromInline private var serializeDefaults: Bool
let serializeDefaults: Bool
/// Current alignment for the buffer /// Current alignment for the buffer
var _minAlignment: Int = 0 { var _minAlignment: Int = 0 {
@@ -489,7 +488,7 @@ public struct FlatBufferBuilder {
/// ///
/// - Parameter bytes: bytes to be written into the buffer /// - Parameter bytes: bytes to be written into the buffer
/// - Returns: ``Offset`` of the vector /// - Returns: ``Offset`` of the vector
mutating public func createVector(bytes: any ContiguousBytes) -> Offset { mutating public func createVector(bytes: ContiguousBytes) -> Offset {
bytes.withUnsafeBytes { bytes.withUnsafeBytes {
startVector($0.count, elementSize: MemoryLayout<UInt8>.size) startVector($0.count, elementSize: MemoryLayout<UInt8>.size)
_bb.push(bytes: $0) _bb.push(bytes: $0)
@@ -757,7 +756,6 @@ public struct FlatBufferBuilder {
/// - offset: ``Offset`` of another object to be written /// - offset: ``Offset`` of another object to be written
/// - position: The predefined position of the object /// - position: The predefined position of the object
@inline(__always) @inline(__always)
@inlinable
mutating public func add(offset: Offset, at position: VOffset) { mutating public func add(offset: Offset, at position: VOffset) {
if offset.isEmpty { return } if offset.isEmpty { return }
add(element: refer(to: offset.o), def: 0, at: position) add(element: refer(to: offset.o), def: 0, at: position)
@@ -796,7 +794,6 @@ public struct FlatBufferBuilder {
/// - def: Default value for that element /// - def: Default value for that element
/// - position: The predefined position of the element /// - position: The predefined position of the element
@inline(__always) @inline(__always)
@inlinable
mutating public func add<T: Scalar>( mutating public func add<T: Scalar>(
element: T, element: T,
def: T, def: T,
@@ -816,7 +813,6 @@ public struct FlatBufferBuilder {
/// - element: Optional element of type scalar /// - element: Optional element of type scalar
/// - position: The predefined position of the element /// - position: The predefined position of the element
@inline(__always) @inline(__always)
@inlinable
mutating public func add<T: Scalar>(element: T?, at position: VOffset) { mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
guard let element = element else { return } guard let element = element else { return }
track(offset: push(element: element), at: position) track(offset: push(element: element), at: position)
@@ -829,7 +825,6 @@ public struct FlatBufferBuilder {
/// - Parameter element: Element to insert /// - Parameter element: Element to insert
/// - returns: position of the Element /// - returns: position of the Element
@inline(__always) @inline(__always)
@inlinable
@discardableResult @discardableResult
mutating public func push<T: Scalar>(element: T) -> UOffset { mutating public func push<T: Scalar>(element: T) -> UOffset {
let size = MemoryLayout<T>.size let size = MemoryLayout<T>.size
@@ -841,8 +836,7 @@ public struct FlatBufferBuilder {
} }
@inline(__always) @inline(__always)
@inlinable public func read<T>(def: T.Type, position: Int) -> T {
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_bb.read(def: def, position: position) _bb.read(def: def, position: position)
} }
} }
@@ -18,9 +18,7 @@ import Foundation
/// NativeStruct is a protocol that indicates if the struct is a native `swift` struct /// 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. /// since now we will be serializing native structs into the buffer.
public protocol NativeStruct: BitwiseCopyable {} public protocol NativeStruct {}
public protocol FlatBufferVerifiableNativeStruct: NativeStruct, Verifiable {}
/// FlatbuffersInitializable is a protocol that allows any object to be /// FlatbuffersInitializable is a protocol that allows any object to be
/// Initialized from a ByteBuffer /// Initialized from a ByteBuffer
@@ -37,8 +35,6 @@ public protocol FlatBufferTable: FlatbuffersInitializable,
var __buffer: ByteBuffer! { get } var __buffer: ByteBuffer! { get }
} }
public protocol FlatBufferVerifiableTable: FlatBufferTable, Verifiable {}
/// FlatbufferStruct structures all the Flatbuffers structs /// FlatbufferStruct structures all the Flatbuffers structs
public protocol FlatBufferStruct: FlatbuffersInitializable, public protocol FlatBufferStruct: FlatbuffersInitializable,
FlatbuffersVectorInitializable FlatbuffersVectorInitializable
+30 -59
View File
@@ -16,52 +16,50 @@
import Foundation import Foundation
enum FlatbuffersGRPCError: Error { /// FlatBufferGRPCMessage protocol that should allow us to invoke
case finishedNotCalledOnBuilder /// initializers directly from the GRPC generated code
} public protocol FlatBufferGRPCMessage {
/// Size of readable bytes in the buffer
var size: Int { get }
public protocol GRPCVerifiableMessage<Message> {
associatedtype Message
init(pointer: UnsafeRawBufferPointer)
init(byteBuffer: ByteBuffer) init(byteBuffer: ByteBuffer)
func decode() throws -> Message @discardableResult
func withUnsafeReadableBytes<Data>( @inline(__always)
func withUnsafeReadableBytes<T>(
_ body: (UnsafeRawBufferPointer) throws _ body: (UnsafeRawBufferPointer) throws
-> Data) rethrows -> Data -> T) rethrows -> T
} }
public struct GRPCMessage< /// Message is a wrapper around Buffers to to able to send Flatbuffers `Buffers` through the
Table: FlatBufferVerifiableTable /// GRPC library
>: Sendable, GRPCVerifiableMessage { public struct Message<T: FlatBufferTable>: FlatBufferGRPCMessage {
public typealias Message = Table internal var buffer: ByteBuffer
private let buffer: ByteBuffer /// 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))
}
public var size: Int { Int(buffer.size) } public var size: Int { Int(buffer.size) }
public init(pointer: UnsafeRawBufferPointer) { /// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over
buffer = ByteBuffer( /// GRPC
copyingMemoryBound: pointer.baseAddress!, /// - Parameter byteBuffer: Flatbuffer ByteBuffer object
capacity: pointer.count)
}
public init(builder: inout FlatBufferBuilder) throws {
guard builder.finished else {
throw FlatbuffersGRPCError.finishedNotCalledOnBuilder
}
buffer = builder.sizedBuffer
}
public init(byteBuffer: ByteBuffer) { public init(byteBuffer: ByteBuffer) {
buffer = byteBuffer buffer = byteBuffer
} }
public func decode() throws -> Table { /// Initializes the message by copying the buffer to the message to be sent.
var buf = buffer /// from the builder
return try getCheckedRoot(byteBuffer: &buf) /// - 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()
} }
@discardableResult @discardableResult
@@ -75,30 +73,3 @@ public struct GRPCMessage<
} }
} }
} }
@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)
}
}
+7 -7
View File
@@ -49,7 +49,7 @@ public struct Table {
/// the vtable /// the vtable
/// - Parameter o: current offset /// - Parameter o: current offset
/// - Returns: offset of field within buffer /// - Returns: offset of field within buffer
public func offset(_ o: VOffset) -> Int32 { public func offset(_ o: Int32) -> Int32 {
let vtable = position &- bb.read(def: Int32.self, position: Int(position)) let vtable = position &- bb.read(def: Int32.self, position: Int(position))
return o return o
< bb < bb
@@ -57,7 +57,7 @@ public struct Table {
? Int32( ? Int32(
bb.read( bb.read(
def: Int16.self, def: Int16.self,
position: Int(vtable &+ Int32(o)))) : 0 position: Int(vtable &+ o))) : 0
} }
/// Gets the indirect offset of the current stored object /// Gets the indirect offset of the current stored object
@@ -82,7 +82,7 @@ public struct Table {
/// - Parameters: /// - Parameters:
/// - type: Type of Element that needs to be read from the buffer /// - type: Type of Element that needs to be read from the buffer
/// - o: Offset of the Element /// - o: Offset of the Element
public func readBuffer<T: BitwiseCopyable>(of type: T.Type, at o: Int32) -> T { public func readBuffer<T>(of type: T.Type, at o: Int32) -> T {
bb.read(def: T.self, position: Int(o &+ position)) bb.read(def: T.self, position: Int(o &+ position))
} }
@@ -106,13 +106,13 @@ public struct Table {
/// This should only be used by `Scalars` /// This should only be used by `Scalars`
/// - Parameter off: Readable offset /// - Parameter off: Readable offset
/// - Returns: Returns a vector of type [T] /// - Returns: Returns a vector of type [T]
public func getVector<T>(at off: VOffset) -> [T]? { public func getVector<T>(at off: Int32) -> [T]? {
let o = offset(off) let o = offset(off)
guard o != 0 else { return nil } guard o != 0 else { return nil }
return bb.readSlice(index: Int(vector(at: o)), count: Int(vector(count: o))) return bb.readSlice(index: Int(vector(at: o)), count: Int(vector(count: o)))
} }
public func vector<T>(at off: VOffset, byteSize: Int) -> FlatbufferVector<T> { public func vector<T>(at off: Int32, byteSize: Int) -> FlatbufferVector<T> {
let off = offset(off) let off = offset(off)
return FlatbufferVector( return FlatbufferVector(
bb: bb, bb: bb,
@@ -122,7 +122,7 @@ public struct Table {
} }
public func unionVector( public func unionVector(
at off: VOffset, at off: Int32,
byteSize: Int) -> UnionFlatbufferVector byteSize: Int) -> UnionFlatbufferVector
{ {
let off = offset(off) let off = offset(off)
@@ -146,7 +146,7 @@ public struct Table {
/// - Returns: Returns a pointer to the underlying data /// - Returns: Returns a pointer to the underlying data
@inline(__always) @inline(__always)
public func withUnsafePointerToSlice<T>( public func withUnsafePointerToSlice<T>(
at off: VOffset, at off: Int32,
body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T? body: (UnsafeRawBufferPointer, Int) throws -> T) rethrows -> T?
{ {
let o = offset(off) let o = offset(off)
@@ -115,7 +115,7 @@ public struct TableVerifier {
unionKeyName: String, unionKeyName: String,
fieldName: String, fieldName: String,
required: Bool, required: Bool,
completion: (inout Verifier, T, Int) throws -> Void) throws completion: @escaping (inout Verifier, T, Int) throws -> Void) throws
where T: UnionEnum where T: UnionEnum
{ {
let keyPos = try dereference(key) let keyPos = try dereference(key)
@@ -68,7 +68,7 @@ public struct FlatbufferVector<
} }
extension FlatbufferVector: Encodable where Element: Encodable { extension FlatbufferVector: Encodable where Element: Encodable {
public func encode(to encoder: any Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer() var container = encoder.unkeyedContainer()
for element in self { for element in self {
try container.encode(element) try container.encode(element)
@@ -49,8 +49,8 @@ public struct UnionFlatbufferVector {
public subscript( public subscript(
position: Int, position: Int,
Type: any FlatbuffersVectorInitializable Type: FlatbuffersVectorInitializable
.Type) -> any FlatbuffersVectorInitializable .Type) -> FlatbuffersVectorInitializable
{ {
guard position < count else { guard position < count else {
fatalError( fatalError(
+1 -8
View File
@@ -56,15 +56,8 @@ extension Verifiable {
let len: UOffset = try verifier.getValue(at: position) let len: UOffset = try verifier.getValue(at: position)
let intLen = Int(len) let intLen = Int(len)
let start = Int(clamping: (position &+ MemoryLayout<Int32>.size).magnitude) 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.isAligned(position: start, type: type.self)
try verifier.rangeInBuffer(position: start, size: byteCount.partialValue) try verifier.rangeInBuffer(position: start, size: intLen)
return (start, intLen) return (start, intLen)
} }
} }
+1 -1
View File
@@ -163,7 +163,7 @@ public struct Verifier {
/// - Parameter position: Current position to be read /// - Parameter position: Current position to be read
/// - Throws: `inBuffer` errors /// - Throws: `inBuffer` errors
/// - Returns: a value of type `T` usually a `VTable` or a table offset /// - Returns: a value of type `T` usually a `VTable` or a table offset
internal func getValue<T: BitwiseCopyable>(at position: Int) throws -> T { internal func getValue<T>(at position: Int) throws -> T {
try inBuffer(position: position, of: T.self) try inBuffer(position: position, of: T.self)
return _buffer.read(def: T.self, position: position) return _buffer.read(def: T.self, position: position)
} }
@@ -30,7 +30,7 @@ struct _InternalByteBuffer {
@usableFromInline @usableFromInline
final class Storage { final class Storage {
/// pointer to the start of the buffer object in memory /// pointer to the start of the buffer object in memory
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer private(set) var memory: UnsafeMutableRawPointer
@usableFromInline @usableFromInline
init(count: Int, alignment: Int) { init(count: Int, alignment: Int) {
@@ -146,7 +146,7 @@ struct _InternalByteBuffer {
#if !os(WASI) #if !os(WASI)
@inline(__always) @inline(__always)
@usableFromInline @usableFromInline
mutating func push(bytes: any ContiguousBytes) { mutating func push(bytes: ContiguousBytes) {
bytes.withUnsafeBytes { ptr in bytes.withUnsafeBytes { ptr in
ensureSpace(size: ptr.count) ensureSpace(size: ptr.count)
memcpy( memcpy(
@@ -333,7 +333,6 @@ struct _InternalByteBuffer {
@discardableResult @discardableResult
@inline(__always) @inline(__always)
@usableFromInline
func readWithUnsafeRawPointer<T>( func readWithUnsafeRawPointer<T>(
position: Int, position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T _ body: (UnsafeRawPointer) throws -> T) rethrows -> T
+11 -28
View File
@@ -27,32 +27,15 @@ public struct ByteBuffer {
@usableFromInline @usableFromInline
final class Storage { final class Storage {
@usableFromInline @usableFromInline
@frozen enum Blob: ~Copyable { enum Blob {
#if !os(WASI) #if !os(WASI)
case data(Data) case data(Data)
case bytes(any ContiguousBytes) case bytes(ContiguousBytes)
#endif #endif
case byteBuffer(_InternalByteBuffer) case byteBuffer(_InternalByteBuffer)
case array([UInt8]) case array([UInt8])
case pointer(UnsafeMutableRawPointer) 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. /// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -61,7 +44,7 @@ public struct ByteBuffer {
private let capacity: Int private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to. /// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline @usableFromInline
let retainedBlob: Blob var retainedBlob: Blob
@usableFromInline @usableFromInline
init(count: Int) { init(count: Int) {
@@ -74,9 +57,9 @@ public struct ByteBuffer {
} }
@usableFromInline @usableFromInline
init(blob: borrowing Blob, capacity count: Int) { init(blob: Blob, capacity count: Int) {
capacity = count capacity = count
retainedBlob = .init(blob) retainedBlob = blob
isOwned = false isOwned = false
} }
@@ -293,7 +276,7 @@ public struct ByteBuffer {
/// - removeBytes: Removes a number of bytes from the current size /// - removeBytes: Removes a number of bytes from the current size
@inline(__always) @inline(__always)
init( init(
blob: borrowing Storage.Blob, blob: Storage.Blob,
count: Int, count: Int,
removing removeBytes: Int) removing removeBytes: Int)
{ {
@@ -333,7 +316,7 @@ public struct ByteBuffer {
/// - def: Type of the object /// - def: Type of the object
/// - position: the index of the object in the buffer /// - position: the index of the object in the buffer
@inline(__always) @inline(__always)
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T { public func read<T>(def: T.Type, position: Int) -> T {
_storage.readWithUnsafeRawPointer(position: position) { _storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1) $0.bindMemory(to: T.self, capacity: 1)
.pointee .pointee
@@ -377,10 +360,10 @@ public struct ByteBuffer {
@inline(__always) @inline(__always)
func readSizedScalar< func readSizedScalar<
T: BinaryInteger, T: BinaryInteger,
T1: BinaryInteger & BitwiseCopyable, T1: BinaryInteger,
T2: BinaryInteger & BitwiseCopyable, T2: BinaryInteger,
T3: BinaryInteger & BitwiseCopyable, T3: BinaryInteger,
T4: BinaryInteger & BitwiseCopyable T4: BinaryInteger
>( >(
def: T.Type, def: T.Type,
t1: T1.Type, t1: T1.Type,
@@ -16,7 +16,7 @@
import Foundation import Foundation
public enum FlexBufferType: UInt64, Sendable { public enum FlexBufferType: UInt64 {
case null = 0 case null = 0
/// Variable width signed integer: `Int8, Int16, Int32, Int64` /// Variable width signed integer: `Int8, Int16, Int32, Int64`
case int = 1 case int = 1
@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
import Common
import Foundation import Foundation
enum FlexBuffersErrors: Error { enum FlexBuffersErrors: Error {
@@ -24,10 +23,6 @@ enum FlexBuffersErrors: Error {
@inline(__always) @inline(__always)
public func getRoot(buffer: ByteBuffer) throws -> Reference? { public func getRoot(buffer: ByteBuffer) throws -> Reference? {
assert(
isLitteEndian,
"Swift FlexBuffers currently only supports little-endian systems")
let end = buffer.count let end = buffer.count
if buffer.count < 3 { if buffer.count < 3 {
throw FlexBuffersErrors.sizeOfBufferIsTooSmall throw FlexBuffersErrors.sizeOfBufferIsTooSmall
@@ -17,7 +17,7 @@
import Foundation import Foundation
@usableFromInline @usableFromInline
enum BitWidth: UInt64, CaseIterable, Sendable { enum BitWidth: UInt64, CaseIterable {
case w8 = 0 case w8 = 0
case w16 = 1 case w16 = 1
case w32 = 2 case w32 = 2
+2 -2
View File
@@ -20,10 +20,10 @@ import Foundation
import Common import Common
#endif #endif
public struct Value: Equatable, Sendable { public struct Value: Equatable {
@usableFromInline @usableFromInline
enum Union: Equatable, Sendable { enum Union: Equatable {
case i(Int64) case i(Int64)
case u(UInt64) case u(UInt64)
case f(Double) case f(Double)
@@ -37,15 +37,12 @@ public struct FlexBuffersWriter {
private var hasDuplicatedKeys = false private var hasDuplicatedKeys = false
private var minBitWidth: BitWidth = .w8 private var minBitWidth: BitWidth = .w8
private var _bb: _InternalByteBuffer private var _bb: _InternalByteBuffer
private var stack: Stack = Stack() private var stack: [Value] = []
private var keyPool: [Int: UInt] = [:] private var keyPool: [Int: UInt] = [:]
private var stringPool: [Int: UInt] = [:] private var stringPool: [Int: UInt] = [:]
private var flags: BuilderFlag private var flags: BuilderFlag
public init(initialSize: Int = 1024, flags: BuilderFlag = .shareKeys) { public init(initialSize: Int = 1024, flags: BuilderFlag = .shareKeys) {
assert(
isLitteEndian,
"Swift FlexBuffers currently only supports little-endian systems")
_bb = _InternalByteBuffer(initialSize: initialSize) _bb = _InternalByteBuffer(initialSize: initialSize)
self.flags = flags self.flags = flags
} }
@@ -151,7 +148,7 @@ public struct FlexBuffersWriter {
typed: typed, typed: typed,
fixed: fixed, fixed: fixed,
keys: nil) keys: nil)
stack.popLast(start) stack = Array(stack[..<start])
stack.append(vec) stack.append(vec)
return vec.u return vec.u
} }
@@ -220,7 +217,7 @@ public struct FlexBuffersWriter {
typed: false, typed: false,
fixed: false, fixed: false,
keys: keys) keys: keys)
stack.popLast(start) stack = Array(stack[..<start])
stack.append(vec) stack.append(vec)
return numericCast(vec.u) return numericCast(vec.u)
} }
@@ -724,7 +721,7 @@ public struct FlexBuffersWriter {
assert( assert(
vectorType == stack[i].type, 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 with elements that are not all the same type
""") """)
} }
@@ -760,7 +757,7 @@ public struct FlexBuffersWriter {
} }
if !fixed { if !fixed {
write(value: UInt64(count), byteWidth: byteWidth) write(value: count, byteWidth: byteWidth)
} }
let vloc = _bb.writerIndex let vloc = _bb.writerIndex
@@ -833,14 +830,13 @@ public struct FlexBuffersWriter {
let key, value: Value let key, value: Value
} }
stack.withUnsafeMutableBytes(start: start) { buffer in stack[start...].withUnsafeMutableBytes { buffer in
var ptr = buffer.assumingMemoryBound(to: TwoValue.self) var ptr = buffer.assumingMemoryBound(to: TwoValue.self)
ptr.sort { a, b in ptr.sort { a, b in
let aMem = _bb.memory.advanced(by: numericCast(a.key.u)) let aMem = _bb.memory.advanced(by: numericCast(a.key.u))
.assumingMemoryBound(to: CChar.self) .assumingMemoryBound(to: CChar.self)
let bMem = _bb.memory.advanced(by: numericCast(b.key.u)) let bMem = _bb.memory.advanced(by: numericCast(b.key.u))
.assumingMemoryBound(to: CChar.self) .assumingMemoryBound(to: CChar.self)
let comp = strcmp(aMem, bMem) let comp = strcmp(aMem, bMem)
if (comp == 0) && a != b { hasDuplicatedKeys = true } if (comp == 0) && a != b { hasDuplicatedKeys = true }
return comp < 0 return comp < 0
@@ -901,132 +897,3 @@ extension FlexBuffersWriter {
return endMap(start: start) 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 @usableFromInline
final class Storage { final class Storage {
/// pointer to the start of the buffer object in memory /// pointer to the start of the buffer object in memory
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer var memory: UnsafeMutableRawPointer
@usableFromInline @usableFromInline
init(count: Int, alignment: Int) { init(count: Int, alignment: Int) {
@@ -60,7 +60,7 @@ struct _InternalByteBuffer {
let newData = UnsafeMutableRawPointer.allocate( let newData = UnsafeMutableRawPointer.allocate(
byteCount: capacity, byteCount: capacity,
alignment: alignment) alignment: alignment)
memset(newData, 0, capacity) memset(newData, 0, capacity &- writerSize)
memcpy( memcpy(
newData, newData,
memory, memory,
+17 -13
View File
@@ -52,7 +52,6 @@ cc_test(
"monster_test.cpp", "monster_test.cpp",
"monster_test.h", "monster_test.h",
"monster_test_bfbs_generated.h", "monster_test_bfbs_generated.h",
"cross_namespace_pack_test_generated.h",
"namespace_test/namespace_test1_generated.h", "namespace_test/namespace_test1_generated.h",
"namespace_test/namespace_test2_generated.h", "namespace_test/namespace_test2_generated.h",
"native_inline_table_test_generated.h", "native_inline_table_test_generated.h",
@@ -79,6 +78,9 @@ cc_test(
"vector_table_naked_ptr/vector_table_naked_ptr_generated.h", "vector_table_naked_ptr/vector_table_naked_ptr_generated.h",
"vector_table_naked_ptr_test.h", "vector_table_naked_ptr_test.h",
"vector_table_naked_ptr_test.cpp", "vector_table_naked_ptr_test.cpp",
"test_vector_type.h",
"cpp_vector_type_test.h",
"cpp_vector_type_test.cpp",
], ],
copts = [ copts = [
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE", "-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
@@ -137,7 +139,7 @@ cc_test(
deps = [ deps = [
":alignment_test_cc_fbs", ":alignment_test_cc_fbs",
":arrays_test_cc_fbs", ":arrays_test_cc_fbs",
":cross_namespace_pack_test_cc_fbs", ":cpp_vector_type_cc_fbs",
":default_vectors_strings_test_cc_fbs", ":default_vectors_strings_test_cc_fbs",
":monster_extra_cc_fbs", ":monster_extra_cc_fbs",
":monster_test_cc_fbs", ":monster_test_cc_fbs",
@@ -263,17 +265,6 @@ 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( flatbuffer_cc_library(
name = "native_type_test_cc_fbs", name = "native_type_test_cc_fbs",
srcs = ["native_type_test.fbs"], srcs = ["native_type_test.fbs"],
@@ -284,6 +275,19 @@ 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( flatbuffer_cc_library(
name = "alignment_test_cc_fbs", name = "alignment_test_cc_fbs",
srcs = ["alignment_test.fbs"], srcs = ["alignment_test.fbs"],
@@ -106,9 +106,6 @@
<Compile Include="..\MyGame\Example\NestedStruct.cs"> <Compile Include="..\MyGame\Example\NestedStruct.cs">
<Link>MyGame\Example\NestedStruct.cs</Link> <Link>MyGame\Example\NestedStruct.cs</Link>
</Compile> </Compile>
<Compile Include="..\MyGame\Example\LargeArrayStruct.cs">
<Link>MyGame\Example\LargeArrayStruct.cs</Link>
</Compile>
<Compile Include="..\MyGame\Example\LongEnum.cs"> <Compile Include="..\MyGame\Example\LongEnum.cs">
<Link>MyGame\Example\LongEnum.cs</Link> <Link>MyGame\Example\LongEnum.cs</Link>
</Compile> </Compile>
-150
View File
@@ -1,150 +0,0 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace MyGame.Example
{
using global::System;
using global::System.Collections.Generic;
using global::Google.FlatBuffers;
public struct LargeArrayStruct : IFlatbufferObject
{
private Struct __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); }
public LargeArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public byte D(int j) { return __p.bb.Get(__p.bb_pos + 0 + j * 1); }
public const int DLength = 64;
#if ENABLE_SPAN_T
public Span<byte> GetDBytes() { return __p.bb.ToSpan(__p.bb_pos + 0, 64); }
#else
public ArraySegment<byte>? GetDBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 0, 64);}
#endif
public void MutateD(int j, byte d) { __p.bb.Put(__p.bb_pos + 0 + j * 1, d); }
public float E(int j) { return __p.bb.GetFloat(__p.bb_pos + 64 + j * 4); }
public const int ELength = 64;
#if ENABLE_SPAN_T
public Span<float> GetEBytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, float>(__p.bb.ToSpan(__p.bb_pos + 64, 256)); }
#else
public ArraySegment<byte>? GetEBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 64, 256);}
#endif
public void MutateE(int j, float e) { __p.bb.PutFloat(__p.bb_pos + 64 + j * 4, e); }
public bool F(int j) { return 0!=__p.bb.Get(__p.bb_pos + 320 + j * 1); }
public const int FLength = 64;
#if ENABLE_SPAN_T
public Span<bool> GetFBytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, bool>(__p.bb.ToSpan(__p.bb_pos + 320, 64)); }
#else
public ArraySegment<byte>? GetFBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 320, 64);}
#endif
public void MutateF(int j, bool f) { __p.bb.Put(__p.bb_pos + 320 + j * 1, (byte)(f ? 1 : 0)); }
public MyGame.Example.NestedStruct G(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 384 + j * 32, __p.bb); }
public MyGame.Example.TestEnum H(int j) { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 2432 + j * 1); }
public const int HLength = 64;
#if ENABLE_SPAN_T
public Span<MyGame.Example.TestEnum> GetHBytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, MyGame.Example.TestEnum>(__p.bb.ToSpan(__p.bb_pos + 2432, 64)); }
#else
public ArraySegment<byte>? GetHBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 2432, 64);}
#endif
public void MutateH(int j, MyGame.Example.TestEnum h) { __p.bb.PutSbyte(__p.bb_pos + 2432 + j * 1, (sbyte)h); }
public static Offset<MyGame.Example.LargeArrayStruct> CreateLargeArrayStruct(FlatBufferBuilder builder, byte[] D, float[] E, bool[] F, int[,] g_A, MyGame.Example.TestEnum[] g_B, MyGame.Example.TestEnum[,] g_C, long[,] g_D, MyGame.Example.TestEnum[] H) {
builder.Prep(8, 2496);
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.PutSbyte((sbyte)H[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.Prep(8, 32);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.PutLong(g_D[_idx0-1,_idx1-1]);
}
builder.Pad(5);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.PutSbyte((sbyte)g_C[_idx0-1,_idx1-1]);
}
builder.PutSbyte((sbyte)g_B[_idx0-1]);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.PutInt(g_A[_idx0-1,_idx1-1]);
}
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.PutBool(F[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.PutFloat(E[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.PutByte(D[_idx0-1]);
}
return new Offset<MyGame.Example.LargeArrayStruct>(builder.Offset);
}
public LargeArrayStructT UnPack() {
var _o = new LargeArrayStructT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(LargeArrayStructT _o) {
_o.D = new byte[64];
for (var _j = 0; _j < 64; ++_j) { _o.D[_j] = this.D(_j); }
_o.E = new float[64];
for (var _j = 0; _j < 64; ++_j) { _o.E[_j] = this.E(_j); }
_o.F = new bool[64];
for (var _j = 0; _j < 64; ++_j) { _o.F[_j] = this.F(_j); }
_o.G = new MyGame.Example.NestedStructT[64];
for (var _j = 0; _j < 64; ++_j) { _o.G[_j] = this.G(_j).UnPack(); }
_o.H = new MyGame.Example.TestEnum[64];
for (var _j = 0; _j < 64; ++_j) { _o.H[_j] = this.H(_j); }
}
public static Offset<MyGame.Example.LargeArrayStruct> Pack(FlatBufferBuilder builder, LargeArrayStructT _o) {
if (_o == null) return default(Offset<MyGame.Example.LargeArrayStruct>);
var _d = _o.D;
var _e = _o.E;
var _f = _o.F;
var _g_a = new int[64,2];
for (var idx0 = 0; idx0 < 64; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_g_a[idx0,idx1] = _o.G[idx0].A[idx1];}}
var _g_b = new MyGame.Example.TestEnum[64];
for (var idx0 = 0; idx0 < 64; ++idx0) {_g_b[idx0] = _o.G[idx0].B;}
var _g_c = new MyGame.Example.TestEnum[64,2];
for (var idx0 = 0; idx0 < 64; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_g_c[idx0,idx1] = _o.G[idx0].C[idx1];}}
var _g_d = new long[64,2];
for (var idx0 = 0; idx0 < 64; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_g_d[idx0,idx1] = _o.G[idx0].D[idx1];}}
var _h = _o.H;
return CreateLargeArrayStruct(
builder,
_d,
_e,
_f,
_g_a,
_g_b,
_g_c,
_g_d,
_h);
}
}
public class LargeArrayStructT
{
[Newtonsoft.Json.JsonProperty("d")]
public byte[] D { get; set; }
[Newtonsoft.Json.JsonProperty("e")]
public float[] E { get; set; }
[Newtonsoft.Json.JsonProperty("f")]
public bool[] F { get; set; }
[Newtonsoft.Json.JsonProperty("g")]
public MyGame.Example.NestedStructT[] G { get; set; }
[Newtonsoft.Json.JsonProperty("h")]
public MyGame.Example.TestEnum[] H { get; set; }
public LargeArrayStructT() {
this.D = new byte[64];
this.E = new float[64];
this.F = new bool[64];
this.G = new MyGame.Example.NestedStructT[64];
this.H = new MyGame.Example.TestEnum[64];
}
}
}
-117
View File
@@ -1,117 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
package MyGame.Example;
import com.google.flatbuffers.BaseVector;
import com.google.flatbuffers.BooleanVector;
import com.google.flatbuffers.ByteVector;
import com.google.flatbuffers.Constants;
import com.google.flatbuffers.DoubleVector;
import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.FloatVector;
import com.google.flatbuffers.IntVector;
import com.google.flatbuffers.LongVector;
import com.google.flatbuffers.ShortVector;
import com.google.flatbuffers.StringVector;
import com.google.flatbuffers.Struct;
import com.google.flatbuffers.UnionVector;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@SuppressWarnings("unused")
public final class LargeArrayStruct extends Struct {
public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
public LargeArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public int d(int j) { return bb.get(bb_pos + 0 + j * 1); }
public void mutateD(int j, int d) { bb.put(bb_pos + 0 + j * 1, (byte) d); }
public float e(int j) { return bb.getFloat(bb_pos + 64 + j * 4); }
public void mutateE(int j, float e) { bb.putFloat(bb_pos + 64 + j * 4, e); }
public boolean f(int j) { return 0!=bb.get(bb_pos + 320 + j * 1); }
public void mutateF(int j, boolean f) { bb.put(bb_pos + 320 + j * 1, (byte)(f ? 1 : 0)); }
public MyGame.Example.NestedStruct g(int j) { return g(new MyGame.Example.NestedStruct(), j); }
public MyGame.Example.NestedStruct g(MyGame.Example.NestedStruct obj, int j) { return obj.__assign(bb_pos + 384 + j * 32, bb); }
public byte h(int j) { return bb.get(bb_pos + 2432 + j * 1); }
public void mutateH(int j, byte h) { bb.put(bb_pos + 2432 + j * 1, h); }
public static int createLargeArrayStruct(FlatBufferBuilder builder, int[] d, float[] e, boolean[] f, int[][] g_a, byte[] g_b, byte[][] g_c, long[][] g_d, byte[] h) {
builder.prep(8, 2496);
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.putByte(h[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.prep(8, 32);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.putLong(g_d[_idx0-1][_idx1-1]);
}
builder.pad(5);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.putByte(g_c[_idx0-1][_idx1-1]);
}
builder.putByte(g_b[_idx0-1]);
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
builder.putInt(g_a[_idx0-1][_idx1-1]);
}
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.putBoolean(f[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.putFloat(e[_idx0-1]);
}
for (int _idx0 = 64; _idx0 > 0; _idx0--) {
builder.putByte((byte) d[_idx0-1]);
}
return builder.offset();
}
public static final class Vector extends BaseVector {
public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; }
public LargeArrayStruct get(int j) { return get(new LargeArrayStruct(), j); }
public LargeArrayStruct get(LargeArrayStruct obj, int j) { return obj.__assign(__element(j), bb); }
}
public LargeArrayStructT unpack() {
LargeArrayStructT _o = new LargeArrayStructT();
unpackTo(_o);
return _o;
}
public void unpackTo(LargeArrayStructT _o) {
int[] _oD = _o.getD();
for (int _j = 0; _j < 64; ++_j) { _oD[_j] = d(_j); }
float[] _oE = _o.getE();
for (int _j = 0; _j < 64; ++_j) { _oE[_j] = e(_j); }
boolean[] _oF = _o.getF();
for (int _j = 0; _j < 64; ++_j) { _oF[_j] = f(_j); }
MyGame.Example.NestedStructT[] _oG = _o.getG();
for (int _j = 0; _j < 64; ++_j) { _oG[_j] = g(_j).unpack(); }
byte[] _oH = _o.getH();
for (int _j = 0; _j < 64; ++_j) { _oH[_j] = h(_j); }
}
public static int pack(FlatBufferBuilder builder, LargeArrayStructT _o) {
if (_o == null) return 0;
int[] _d = _o.getD();
float[] _e = _o.getE();
boolean[] _f = _o.getF();
int[][] _g_a = new int[64][2];
for (int idx0 = 0; idx0 < 64; ++idx0) {for (int idx1 = 0; idx1 < 2; ++idx1) {_g_a[idx0][idx1] = _o.getG()[idx0].getA()[idx1];}}
byte[] _g_b = new byte[64];
for (int idx0 = 0; idx0 < 64; ++idx0) {_g_b[idx0] = _o.getG()[idx0].getB();}
byte[][] _g_c = new byte[64][2];
for (int idx0 = 0; idx0 < 64; ++idx0) {for (int idx1 = 0; idx1 < 2; ++idx1) {_g_c[idx0][idx1] = _o.getG()[idx0].getC()[idx1];}}
long[][] _g_d = new long[64][2];
for (int idx0 = 0; idx0 < 64; ++idx0) {for (int idx1 = 0; idx1 < 2; ++idx1) {_g_d[idx0][idx1] = _o.getG()[idx0].getD()[idx1];}}
byte[] _h = _o.getH();
return createLargeArrayStruct(
builder,
_d,
_e,
_f,
_g_a,
_g_b,
_g_c,
_g_d,
_h);
}
}

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