Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] 400711102f Bump microsoft/setup-msbuild from 2 to 3
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2 to 3.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v2...v3)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 14:03:02 +00:00
94 changed files with 2089 additions and 4791 deletions
+6 -6
View File
@@ -137,7 +137,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2 uses: microsoft/setup-msbuild@v3
- name: cmake - name: cmake
run: > run: >
cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
@@ -162,7 +162,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2 uses: microsoft/setup-msbuild@v3
- name: cmake - name: cmake
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON . run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build - name: build
@@ -350,7 +350,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2 uses: microsoft/setup-msbuild@v3
- name: cmake - name: cmake
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON . run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
- name: build - name: build
@@ -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
+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 -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
-55
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
-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 }
@@ -23,16 +23,16 @@ public struct models_HelloResponse: FlatBufferVerifiableTable, FlatbuffersVector
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(VT.message); 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: VT.message) }
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: VT.message) }
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 {
@@ -42,7 +42,7 @@ public struct models_HelloResponse: FlatBufferVerifiableTable, FlatbuffersVector
} }
} }
extension models_HelloResponse: Encodable { extension models_HelloReply: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case message = "message" case message = "message"
} }
@@ -53,7 +53,7 @@ extension models_HelloResponse: Encodable {
} }
} }
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 }
@@ -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
+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;
} }
-6
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':
-2
View File
@@ -1,2 +0,0 @@
packages:
- tests/ts
+28 -49
View File
@@ -12,54 +12,33 @@
# 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', 'Operating System :: OS Independent',
author='Derek Bailey', 'Programming Language :: Python',
author_email='derekbailey@google.com', 'Programming Language :: Python :: 3',
url='https://google.github.io/flatbuffers/', 'Topic :: Software Development :: Libraries :: Python Modules',
long_description=( ],
'Python runtime library for use with the ' project_urls={
'`Flatbuffers <https://google.github.io/flatbuffers/>`_ ' 'Documentation': 'https://google.github.io/flatbuffers/',
'serialization format.' 'Source': 'https://github.com/google/flatbuffers',
), },
packages=['flatbuffers'], )
include_package_data=True,
requires=[],
description='The FlatBuffers serialization format for Python',
classifiers=[
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
],
project_urls={
'Documentation': 'https://google.github.io/flatbuffers/',
'Source': 'https://github.com/google/flatbuffers',
},
)
finally:
if _remove_staged_license and _LOCAL_LICENSE.exists():
_LOCAL_LICENSE.unlink()
+110 -390
View File
@@ -337,43 +337,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 +360,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 +397,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 +405,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 +424,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,31 +439,10 @@ 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. /// Create a utf8 string, and de-duplicate if already created.
@@ -534,20 +452,26 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
#[cfg(feature = "std")] #[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) self.assert_not_nested(
.expect("Flatbuffer allocation failure") "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 offset;
}
let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value());
self.strings_pool.insert(s.to_owned(), address);
address
} }
/// Fallible version of [`create_shared_string`](Self::create_shared_string). /// Create a utf8 string, and de-duplicate if already created.
/// ///
/// Uses a sorted Vec with binary search to track previously written /// Uses a sorted Vec with binary search to track previously written
/// strings when in `no_std` mode. /// strings when in `no_std` mode.
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
#[inline] #[inline]
pub fn try_create_shared_string<'a: 'b, 'b>( pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
&'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",
); );
@@ -570,83 +494,52 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
}); });
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 +553,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 +565,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 +635,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 +650,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 +658,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 +676,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 +725,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 +750,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 +794,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 +814,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 +827,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 +863,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 {
@@ -1302,111 +1129,4 @@ mod tests {
allocs 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 -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(),
)?; )?;
} }
+2 -2
View File
@@ -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 }
@@ -400,7 +400,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 }
+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(
+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 -1
View File
@@ -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()";
} }
} }
+5 -5
View File
@@ -170,8 +170,9 @@ class SwiftGenerator : public BaseGenerator {
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";
@@ -548,14 +549,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";
+1 -9
View File
@@ -4132,15 +4132,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]);
+1 -1
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]));
} }
} }
+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)
}
}
+1 -1
View File
@@ -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))
} }
@@ -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
@@ -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)
@@ -977,9 +977,6 @@ fileprivate struct Stack: RandomAccessCollection {
mutating func removeAll(keepingCapacity keepCapacity: Bool = false) { mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
count = 0 count = 0
if !keepCapacity { if !keepCapacity {
let ptr = storage.memory
defer { ptr.deallocate() }
capacity = Self.initialCapacity capacity = Self.initialCapacity
storage.memory = UnsafeMutableRawPointer.allocate( storage.memory = UnsafeMutableRawPointer.allocate(
byteCount: capacity, byteCount: capacity,
@@ -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) {
+8 -25
View File
@@ -1,6 +1,5 @@
#include "flexbuffers_test.h" #include "flexbuffers_test.h"
#include <memory>
#include <limits> #include <limits>
#include "flatbuffers/flexbuffers.h" #include "flatbuffers/flexbuffers.h"
@@ -14,13 +13,6 @@ namespace tests {
// Shortcuts for the infinity. // Shortcuts for the infinity.
static const auto infinity_d = std::numeric_limits<double>::infinity(); static const auto infinity_d = std::numeric_limits<double>::infinity();
static bool IsAligned(const void* ptr, std::size_t alignment) {
void* p = const_cast<void*>(ptr);
std::size_t space = 2 * alignment;
void* q = std::align(alignment, alignment, p, space);
return q != nullptr && p == ptr && space == 2 * alignment;
}
void FlexBuffersTest() { void FlexBuffersTest() {
flexbuffers::Builder slb(512, flexbuffers::Builder slb(512,
flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS); flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
@@ -37,10 +29,7 @@ void FlexBuffersTest() {
slb.IndirectFloat(4.0f); slb.IndirectFloat(4.0f);
auto i_f = slb.LastValue(); auto i_f = slb.LastValue();
uint8_t blob[] = {77}; uint8_t blob[] = {77};
uint32_t aligned_blob[] = {88, 99}; slb.Blob(blob, 1);
slb.Blob(blob, sizeof blob);
slb.AlignedBlob(aligned_blob, sizeof aligned_blob,
flexbuffers::BIT_WIDTH_32);
slb += false; slb += false;
slb.ReuseValue(i_f); slb.ReuseValue(i_f);
}); });
@@ -73,7 +62,7 @@ void FlexBuffersTest() {
auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap(); auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap();
TEST_EQ(map.size(), 7); TEST_EQ(map.size(), 7);
auto vec = map["vec"].AsVector(); auto vec = map["vec"].AsVector();
TEST_EQ(vec.size(), 7); TEST_EQ(vec.size(), 6);
TEST_EQ(vec[0].AsInt64(), -100); TEST_EQ(vec[0].AsInt64(), -100);
TEST_EQ_STR(vec[1].AsString().c_str(), "Fred"); TEST_EQ_STR(vec[1].AsString().c_str(), "Fred");
TEST_EQ(vec[1].AsInt64(), 0); // Number parsing failed. TEST_EQ(vec[1].AsInt64(), 0); // Number parsing failed.
@@ -91,15 +80,9 @@ void FlexBuffersTest() {
auto blob = vec[3].AsBlob(); auto blob = vec[3].AsBlob();
TEST_EQ(blob.size(), 1); TEST_EQ(blob.size(), 1);
TEST_EQ(blob.data()[0], 77); TEST_EQ(blob.data()[0], 77);
TEST_EQ(vec[4].IsBlob(), true); TEST_EQ(vec[4].IsBool(), true); // Check if type is a bool
auto aligned_blob = vec[4].AsBlob(); TEST_EQ(vec[4].AsBool(), false); // Check if value is false
TEST_EQ(aligned_blob.size(), 8); TEST_EQ(vec[5].AsDouble(), 4.0); // This is shared with vec[2] !
TEST_EQ(reinterpret_cast<const uint32_t*>(aligned_blob.data())[0], 88);
TEST_EQ(reinterpret_cast<const uint32_t*>(aligned_blob.data())[1], 99);
TEST_EQ(IsAligned(aligned_blob.data(), 4), true);
TEST_EQ(vec[5].IsBool(), true); // Check if type is a bool
TEST_EQ(vec[5].AsBool(), false); // Check if value is false
TEST_EQ(vec[6].AsDouble(), 4.0); // This is shared with vec[2] !
auto tvec = map["bar"].AsTypedVector(); auto tvec = map["bar"].AsTypedVector();
TEST_EQ(tvec.size(), 3); TEST_EQ(tvec.size(), 3);
TEST_EQ(tvec[2].AsInt8(), 3); TEST_EQ(tvec[2].AsInt8(), 3);
@@ -124,9 +107,9 @@ void FlexBuffersTest() {
TEST_EQ(vec[2].MutateFloat(2.0f), true); TEST_EQ(vec[2].MutateFloat(2.0f), true);
TEST_EQ(vec[2].AsFloat(), 2.0f); TEST_EQ(vec[2].AsFloat(), 2.0f);
TEST_EQ(vec[2].MutateFloat(3.14159), false); // Double does not fit in float. TEST_EQ(vec[2].MutateFloat(3.14159), false); // Double does not fit in float.
TEST_EQ(vec[5].AsBool(), false); // Is false before change TEST_EQ(vec[4].AsBool(), false); // Is false before change
TEST_EQ(vec[5].MutateBool(true), true); // Can change a bool TEST_EQ(vec[4].MutateBool(true), true); // Can change a bool
TEST_EQ(vec[5].AsBool(), true); // Changed bool is now true TEST_EQ(vec[4].AsBool(), true); // Changed bool is now true
// Parse from JSON: // Parse from JSON:
flatbuffers::Parser parser; flatbuffers::Parser parser;
-87
View File
@@ -248,93 +248,6 @@ void ReflectionTest(const std::string& tests_data_path, uint8_t* flatbuf,
true); true);
} }
// Test that ForAllFields with reverse=true iterates fields in descending
// ID order. This exercises a fix for an operator precedence bug where the
// expression `size() - i + 1` was evaluated as `(size() - i) + 1` instead
// of the correct `size() - (i + 1)`, causing an out-of-bounds read.
void ForAllFieldsReverseTest(const std::string& tests_data_path) {
// Load the binary schema.
std::string bfbsfile;
TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.bfbs").c_str(),
true, &bfbsfile),
true);
// Verify the schema.
flatbuffers::Verifier verifier(
reinterpret_cast<const uint8_t*>(bfbsfile.c_str()), bfbsfile.length());
TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
auto& schema = *reflection::GetSchema(bfbsfile.c_str());
// Use the Stat table which has 3 fields with sequential IDs:
// id:string (id: 0)
// val:long (id: 1)
// count:ushort (id: 2)
auto stat_object = schema.objects()->LookupByKey("MyGame.Example.Stat");
TEST_NOTNULL(stat_object);
TEST_EQ(stat_object->fields()->size(), 3u);
// Test forward iteration: fields should come in ascending ID order (0,1,2).
{
std::vector<uint16_t> forward_ids;
flatbuffers::ForAllFields(
stat_object, /*reverse=*/false,
[&forward_ids](const reflection::Field* field) {
forward_ids.push_back(field->id());
});
TEST_EQ(forward_ids.size(), 3u);
TEST_EQ(forward_ids[0], 0); // id
TEST_EQ(forward_ids[1], 1); // val
TEST_EQ(forward_ids[2], 2); // count
}
// Test reverse iteration: fields should come in descending ID order (2,1,0).
// With the old buggy code `size() - i + 1`, at i=0 this would compute
// index 3 - 0 + 1 = 4, which is out of bounds for a size-3 vector.
{
std::vector<uint16_t> reverse_ids;
flatbuffers::ForAllFields(
stat_object, /*reverse=*/true,
[&reverse_ids](const reflection::Field* field) {
reverse_ids.push_back(field->id());
});
TEST_EQ(reverse_ids.size(), 3u);
TEST_EQ(reverse_ids[0], 2); // count (highest ID first)
TEST_EQ(reverse_ids[1], 1); // val
TEST_EQ(reverse_ids[2], 0); // id (lowest ID last)
}
// Also test with the root Monster table which has many fields and
// non-sequential definition order vs. ID order (e.g., pos=id:0, hp=id:2,
// mana=id:1). This ensures the ID-to-index mapping works correctly.
auto root_table = schema.root_table();
TEST_NOTNULL(root_table);
{
std::vector<uint16_t> forward_ids;
flatbuffers::ForAllFields(
root_table, /*reverse=*/false,
[&forward_ids](const reflection::Field* field) {
forward_ids.push_back(field->id());
});
// Verify ascending order.
for (size_t i = 1; i < forward_ids.size(); ++i) {
TEST_ASSERT(forward_ids[i - 1] < forward_ids[i]);
}
}
{
std::vector<uint16_t> reverse_ids;
flatbuffers::ForAllFields(
root_table, /*reverse=*/true,
[&reverse_ids](const reflection::Field* field) {
reverse_ids.push_back(field->id());
});
// Verify descending order.
for (size_t i = 1; i < reverse_ids.size(); ++i) {
TEST_ASSERT(reverse_ids[i - 1] > reverse_ids[i]);
}
}
}
void MiniReflectFlatBuffersTest(uint8_t* flatbuf) { void MiniReflectFlatBuffersTest(uint8_t* flatbuf) {
auto s = auto s =
flatbuffers::FlatBufferToString(flatbuf, Monster::MiniReflectTypeTable()); flatbuffers::FlatBufferToString(flatbuf, Monster::MiniReflectTypeTable());
-1
View File
@@ -10,7 +10,6 @@ namespace tests {
void ReflectionTest(const std::string& tests_data_path, uint8_t* flatbuf, void ReflectionTest(const std::string& tests_data_path, uint8_t* flatbuf,
size_t length); size_t length);
void ForAllFieldsReverseTest(const std::string& tests_data_path);
void MiniReflectFixedLengthArrayTest(); void MiniReflectFixedLengthArrayTest();
void MiniReflectFlatBuffersTest(uint8_t* flatbuf); void MiniReflectFlatBuffersTest(uint8_t* flatbuf);
@@ -3448,250 +3448,4 @@ fn test_shared_strings_pool_deduplication() {
} }
} // mod flatbuffers_tests } // mod flatbuffers_tests
#[cfg(test)]
mod try_api {
extern crate flatbuffers;
use alloc::vec::Vec;
use flatbuffers::Follow;
use super::my_game;
use super::serialized_example_is_accessible_and_correct;
#[test]
fn try_api_full_table_roundtrip() {
// Build a Monster using exclusively try_* API (mirrors library_code example).
let mut builder = flatbuffers::FlatBufferBuilder::new();
let nested_union_mon = {
let name = builder.try_create_string("Fred").unwrap();
let table_start = builder.start_table();
builder
.try_push_slot_always(my_game::example::Monster::VT_NAME, name)
.unwrap();
builder.try_end_table(table_start).unwrap()
};
let pos = my_game::example::Vec3::new(
1.0,
2.0,
3.0,
3.0,
my_game::example::Color::Green,
&my_game::example::Test::new(5i16, 6i8),
);
let inv = builder.try_create_vector(&[0u8, 1, 2, 3, 4]).unwrap();
let test4 = builder
.try_create_vector(
&[
my_game::example::Test::new(10, 20),
my_game::example::Test::new(30, 40),
][..],
)
.unwrap();
let name = builder.try_create_string("MyMonster").unwrap();
let test1 = builder.try_create_string("test1").unwrap();
let test2 = builder.try_create_string("test2").unwrap();
let testarrayofstring = builder.try_create_vector(&[test1, test2]).unwrap();
let table_start = builder.start_table();
builder
.try_push_slot(my_game::example::Monster::VT_HP, 80i16, 100)
.unwrap();
builder
.try_push_slot_always(my_game::example::Monster::VT_NAME, name)
.unwrap();
builder
.try_push_slot_always(my_game::example::Monster::VT_POS, &pos)
.unwrap();
builder
.try_push_slot(
my_game::example::Monster::VT_TEST_TYPE,
my_game::example::Any::Monster,
my_game::example::Any::NONE,
)
.unwrap();
builder
.try_push_slot_always(my_game::example::Monster::VT_TEST, nested_union_mon)
.unwrap();
builder
.try_push_slot_always(my_game::example::Monster::VT_INVENTORY, inv)
.unwrap();
builder
.try_push_slot_always(my_game::example::Monster::VT_TEST4, test4)
.unwrap();
builder
.try_push_slot_always(
my_game::example::Monster::VT_TESTARRAYOFSTRING,
testarrayofstring,
)
.unwrap();
let root = builder.try_end_table(table_start).unwrap();
builder
.try_finish(root, Some(my_game::example::MONSTER_IDENTIFIER))
.unwrap();
let buf = builder.finished_data();
serialized_example_is_accessible_and_correct(buf, true, false).unwrap();
}
#[test]
fn try_shared_string_deduplication() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let offset1 = builder
.try_create_shared_string("welcome to flatbuffers!!")
.unwrap();
let offset2 = builder.try_create_shared_string("welcome").unwrap();
let offset3 = builder
.try_create_shared_string("welcome to flatbuffers!!")
.unwrap();
assert_ne!(offset2.value(), offset3.value());
assert_eq!(offset1.value(), offset3.value());
builder.reset();
let offset4 = builder.try_create_shared_string("welcome").unwrap();
let offset5 = builder
.try_create_shared_string("welcome to flatbuffers!!")
.unwrap();
assert_ne!(offset2.value(), offset4.value());
assert_ne!(offset5.value(), offset1.value());
builder.reset();
// Shared strings work with an object in between writes
let name = builder.try_create_shared_string("foo").unwrap();
let enemy =
my_game::example::Monster::create(&mut builder, &my_game::example::MonsterArgs {
name: Some(name),
..Default::default()
});
let secondary_name = builder.try_create_shared_string("foo").unwrap();
assert_eq!(name.value(), secondary_name.value());
let args = my_game::example::MonsterArgs {
name: Some(secondary_name),
enemy: Some(enemy),
testarrayofstring: Some(builder.try_create_vector(&[name, secondary_name]).unwrap()),
..Default::default()
};
let main_monster = my_game::example::Monster::create(&mut builder, &args);
builder.try_finish(main_monster, None).unwrap();
let monster =
my_game::example::root_as_monster(builder.finished_data()).unwrap();
assert_eq!(monster.enemy().unwrap().name(), "foo");
let string_vector = monster.testarrayofstring().unwrap();
assert_eq!(string_vector.get(0), "foo");
assert_eq!(string_vector.get(1), "foo");
}
#[test]
fn try_vector_manual_build_roundtrip() {
// Build a vector of scalars manually using try_start_vector / try_push / try_end_vector.
let mut builder = flatbuffers::FlatBufferBuilder::new();
let items: Vec<u32> = vec![10, 20, 30, 40, 50];
builder
.try_start_vector::<u32>(items.len())
.unwrap();
for &v in items.iter().rev() {
builder.try_push::<u32>(v).unwrap();
}
let vecend = builder.try_end_vector::<u32>(items.len()).unwrap();
builder.try_finish_minimal(vecend).unwrap();
let buf = builder.finished_data();
let got = unsafe {
<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u32>>>::follow(&buf[..], 0)
};
let result: Vec<u32> = got.iter().collect();
assert_eq!(result, items);
}
#[test]
fn try_create_vector_roundtrip() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let items: Vec<i64> = vec![-1, 0, 1, i64::MIN, i64::MAX];
let offset = builder.try_create_vector(&items).unwrap();
builder.try_finish_minimal(offset).unwrap();
let buf = builder.finished_data();
let got = unsafe {
<flatbuffers::ForwardsUOffset<flatbuffers::Vector<i64>>>::follow(&buf[..], 0)
};
let result: Vec<i64> = got.iter().collect();
assert_eq!(result, items);
}
#[test]
fn try_create_vector_from_iter_roundtrip() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let items: Vec<f64> = vec![1.0, 2.5, -3.14, 0.0];
let offset = builder
.try_create_vector_from_iter(items.iter().copied())
.unwrap();
builder.try_finish_minimal(offset).unwrap();
let buf = builder.finished_data();
let got = unsafe {
<flatbuffers::ForwardsUOffset<flatbuffers::Vector<f64>>>::follow(&buf[..], 0)
};
let result: Vec<f64> = got.iter().collect();
assert_eq!(result, items);
}
#[test]
fn try_create_byte_string_roundtrip() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let data = b"hello bytes";
let offset = builder.try_create_byte_string(data).unwrap();
builder.try_finish_minimal(offset).unwrap();
let buf = builder.finished_data();
let got = unsafe {
<flatbuffers::ForwardsUOffset<&[u8]>>::follow(&buf[..], 0)
};
assert_eq!(got, data);
}
#[test]
fn try_finish_size_prefixed_roundtrip() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let args = &my_game::example::MonsterArgs {
mana: 200,
hp: 300,
name: Some(builder.try_create_string("bob").unwrap()),
..Default::default()
};
let mon = my_game::example::Monster::create(&mut builder, &args);
builder.try_finish_size_prefixed(mon, None).unwrap();
let buf = builder.finished_data();
let m = flatbuffers::size_prefixed_root::<my_game::example::Monster>(buf).unwrap();
assert_eq!(m.mana(), 200);
assert_eq!(m.hp(), 300);
assert_eq!(m.name(), "bob");
}
#[test]
fn try_finish_with_file_identifier() {
let mut builder = flatbuffers::FlatBufferBuilder::new();
let name = builder.try_create_string("foo").unwrap();
let args = &my_game::example::MonsterArgs {
name: Some(name),
hp: 42,
..Default::default()
};
let mon = my_game::example::Monster::create(&mut builder, &args);
builder
.try_finish(mon, Some(my_game::example::MONSTER_IDENTIFIER))
.unwrap();
let buf = builder.finished_data();
assert!(my_game::example::monster_buffer_has_identifier(buf));
let m = my_game::example::root_as_monster(buf).unwrap();
assert_eq!(m.name(), "foo");
assert_eq!(m.hp(), 42);
}
}
} }
@@ -14,58 +14,51 @@
* limitations under the License. * limitations under the License.
*/ */
import Foundation import XCTest
import Testing
@testable import FlatBuffers @testable import FlatBuffers
struct ByteBufferTests { final class ByteBufferTests: XCTestCase {
@Test
func testCopyingMemory() { func testCopyingMemory() {
let count = 100 let count = 100
let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1) let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1)
let byteBuffer = ByteBuffer(copyingMemoryBound: ptr, capacity: count) let byteBuffer = ByteBuffer(copyingMemoryBound: ptr, capacity: count)
byteBuffer.withUnsafeBytes { memory in byteBuffer.withUnsafeBytes { memory in
#expect(memory.baseAddress! != ptr) XCTAssertNotEqual(memory.baseAddress, ptr)
} }
} }
@Test
func testSamePointer() { func testSamePointer() {
let count = 100 let count = 100
let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1) let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1)
let byteBuffer = ByteBuffer(assumingMemoryBound: ptr, capacity: count) let byteBuffer = ByteBuffer(assumingMemoryBound: ptr, capacity: count)
byteBuffer.withUnsafeBytes { memory in byteBuffer.withUnsafeBytes { memory in
#expect(memory.baseAddress! == ptr) XCTAssertEqual(memory.baseAddress!, ptr)
} }
} }
@Test
func testSameDataPtr() { func testSameDataPtr() {
let count = 100 let count = 100
let ptr = Data(repeating: 0, count: count) let ptr = Data(repeating: 0, count: count)
let byteBuffer = ByteBuffer(data: ptr) let byteBuffer = ByteBuffer(data: ptr)
byteBuffer.withUnsafeBytes { memory in byteBuffer.withUnsafeBytes { memory in
ptr.withUnsafeBytes { ptr in ptr.withUnsafeBytes { ptr in
#expect(memory.baseAddress! == ptr.baseAddress!) XCTAssertEqual(memory.baseAddress!, ptr.baseAddress!)
} }
} }
} }
@Test
func testSameArrayPtr() { func testSameArrayPtr() {
let count = 100 let count = 100
let ptr: [UInt8] = Array(repeating: 0, count: count) let ptr: [UInt8] = Array(repeating: 0, count: count)
let byteBuffer = ByteBuffer(bytes: ptr) let byteBuffer = ByteBuffer(bytes: ptr)
ptr.withUnsafeBytes { ptr in ptr.withUnsafeBytes { ptr in
byteBuffer.withUnsafeBytes { memory in byteBuffer.withUnsafeBytes { memory in
#expect(memory.baseAddress == ptr.baseAddress) XCTAssertEqual(memory.baseAddress, ptr.baseAddress)
} }
} }
} }
@Test
func testReadingDoubleBuffer() { func testReadingDoubleBuffer() {
let count = 8 let count = 8
let array: [Double] = Array(repeating: 8.8, count: count) let array: [Double] = Array(repeating: 8.8, count: count)
@@ -76,16 +69,15 @@ struct ByteBufferTests {
} }
let byteBuffer = ByteBuffer(bytes: bytes) let byteBuffer = ByteBuffer(bytes: bytes)
byteBuffer.withUnsafePointerToSlice(index: 0, count: count) { ptr in byteBuffer.withUnsafePointerToSlice(index: 0, count: count) { ptr in
#expect(ptr.count == count) XCTAssertEqual(ptr.count, count)
bytes.withUnsafeBufferPointer { bytes.withUnsafeBufferPointer {
#expect( XCTAssertEqual(
UnsafeRawPointer($0.baseAddress) == UnsafeRawPointer($0.baseAddress),
UnsafeRawPointer(ptr.baseAddress)) UnsafeRawPointer(ptr.baseAddress))
} }
} }
} }
@Test
func testReadingNativeStructs() { func testReadingNativeStructs() {
let array = [ let array = [
MyGame_Example_Vec3( MyGame_Example_Vec3(
@@ -119,11 +111,11 @@ struct ByteBufferTests {
let byteBuffer = ByteBuffer(bytes: bytes) let byteBuffer = ByteBuffer(bytes: bytes)
byteBuffer byteBuffer
.withUnsafePointerToSlice(index: 0, count: count) { bufferPointer in .withUnsafePointerToSlice(index: 0, count: count) { bufferPointer in
#expect(bufferPointer.count == count) XCTAssertEqual(bufferPointer.count, count)
bytes.withUnsafeBufferPointer { ptr in bytes.withUnsafeBufferPointer { ptr in
#expect( XCTAssertEqual(
UnsafeRawPointer(ptr.baseAddress) == UnsafeRawPointer(ptr.baseAddress),
UnsafeRawPointer(bufferPointer.baseAddress)) UnsafeRawPointer(bufferPointer.baseAddress))
} }
} }
} }
@@ -134,3 +126,7 @@ private struct TestNativeStructs: NativeStruct {
let y: Double let y: Double
let z: Int let z: Int
} }
extension MyGame_Example_Color: CaseIterable {
public static var allCases: [MyGame_Example_Color] = [.red, .blue, .green]
}
@@ -16,22 +16,18 @@
#if compiler(>=6.2) #if compiler(>=6.2)
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersArraysTests { @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
final class FlatBuffersArraysTests: XCTestCase {
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testStructSizes() { func testStructSizes() {
#expect(MemoryLayout<MyGame_Example_NestedStruct>.size == 32) XCTAssertEqual(MemoryLayout<MyGame_Example_NestedStruct>.size, 32)
#expect(MemoryLayout<MyGame_Example_ArrayStruct>.size == 160) XCTAssertEqual(MemoryLayout<MyGame_Example_ArrayStruct>.size, 160)
#expect((MemoryLayout<MyGame_Example_LargeArrayStruct>.size == 2496))
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testGoldenData() { func testGoldenData() {
// swiftformat:disable all // swiftformat:disable all
let data: [UInt8] = [ let data: [UInt8] = [
@@ -48,11 +44,9 @@ struct FlatBuffersArraysTests {
] ]
// swiftformat:enable all // swiftformat:enable all
#expect(data == createArrayTable()) XCTAssertEqual(data, createArrayTable())
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testData() throws { func testData() throws {
var buf = ByteBuffer(bytes: createArrayTable()) var buf = ByteBuffer(bytes: createArrayTable())
let table: MyGame_Example_ArrayTable = try getCheckedRoot( let table: MyGame_Example_ArrayTable = try getCheckedRoot(
@@ -63,8 +57,6 @@ struct FlatBuffersArraysTests {
verifyNativeStruct(a: table.a) verifyNativeStruct(a: table.a)
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testObjectAPI() throws { func testObjectAPI() throws {
var buf = ByteBuffer(bytes: createArrayTable()) var buf = ByteBuffer(bytes: createArrayTable())
let table: MyGame_Example_ArrayTable = try getCheckedRoot( let table: MyGame_Example_ArrayTable = try getCheckedRoot(
@@ -73,110 +65,105 @@ struct FlatBuffersArraysTests {
verifyNativeStruct(a: table.unpack().a) verifyNativeStruct(a: table.unpack().a)
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testDefaults() { func testDefaults() {
#expect( XCTAssertEqual(
MyGame_Example_NestedStruct() == MyGame_Example_NestedStruct(),
MyGame_Example_NestedStruct( MyGame_Example_NestedStruct(
a: [0, 0], a: [0, 0],
b: .a, b: .a,
c: [0, 0], c: [0, 0],
d: [0, 0])) d: [0, 0]))
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
func verifyNativeStruct(a: MyGame_Example_ArrayStruct?) { func verifyNativeStruct(a: MyGame_Example_ArrayStruct?) {
let a = a! let a = a!
#expect(a.a == 12.34) XCTAssertEqual(a.a, 12.34)
#expect(a.b.count == 15) XCTAssertEqual(a.b.count, 15)
var sum: Int32 = 0 var sum: Int32 = 0
for i in a.b.startIndex..<a.b.endIndex { for i in a.b.startIndex..<a.b.endIndex {
sum += a.b[i] sum += a.b[i]
} }
#expect(sum == 120) XCTAssertEqual(sum, 120)
#expect(a.c == -127) XCTAssertEqual(a.c, -127)
#expect(a.d.count == 2) XCTAssertEqual(a.d.count, 2)
let nestedStruct1 = a.d[0] let nestedStruct1 = a.d[0]
#expect(nestedStruct1.a.toArray() == [-1, 2]) XCTAssertEqual(nestedStruct1.a.toArray(), [-1, 2])
#expect(nestedStruct1.b == .a) XCTAssertEqual(nestedStruct1.b, .a)
#expect(nestedStruct1.c.toArray() == [.c, .b]) XCTAssertEqual(nestedStruct1.c.toArray(), [.c, .b])
#expect( XCTAssertEqual(
nestedStruct1.d.toArray() == nestedStruct1.d.toArray(),
[0x1122334455667788, -0x1122334455667788]) [0x1122334455667788, -0x1122334455667788])
let nestedStruct2 = a.d[1] let nestedStruct2 = a.d[1]
#expect(nestedStruct2.a.toArray() == [3, -4]) XCTAssertEqual(nestedStruct2.a.toArray(), [3, -4])
#expect(nestedStruct2.b == .b) XCTAssertEqual(nestedStruct2.b, .b)
#expect(nestedStruct2.c.toArray() == [.b, .a]) XCTAssertEqual(nestedStruct2.c.toArray(), [.b, .a])
#expect( XCTAssertEqual(
nestedStruct2.d.toArray() == nestedStruct2.d.toArray(),
[-0x1122334455667788, 0x1122334455667788]) [-0x1122334455667788, 0x1122334455667788])
#expect(a.e == 1) XCTAssertEqual(a.e, 1)
#expect(a.f.count == 2) XCTAssertEqual(a.f.count, 2)
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
func verifyMutations(in table: MyGame_Example_ArrayTable) { func verifyMutations(in table: MyGame_Example_ArrayTable) {
let a = table.mutableA! let a = table.mutableA!
#expect(a.a == 12.34) XCTAssertEqual(a.a, 12.34)
#expect(a.b.count == 15) XCTAssertEqual(a.b.count, 15)
var sum: Int32 = 0 var sum: Int32 = 0
for i in a.b.startIndex..<a.b.endIndex { for i in a.b.startIndex..<a.b.endIndex {
sum += a.b[i] sum += a.b[i]
} }
#expect(sum == 120) XCTAssertEqual(sum, 120)
#expect(a.c == -127) XCTAssertEqual(a.c, -127)
#expect(a.d.count == 2) XCTAssertEqual(a.d.count, 2)
let nestedStruct1 = a.d[0] let nestedStruct1 = a.d[0]
#expect(nestedStruct1.a.reduce(0) { $0 + $1 } == 1) XCTAssertEqual(nestedStruct1.a.reduce(0) { $0 + $1 }, 1)
#expect(nestedStruct1.b == .a) XCTAssertEqual(nestedStruct1.b, .a)
#expect(nestedStruct1.c[0] == .c) XCTAssertEqual(nestedStruct1.c[0], .c)
#expect(nestedStruct1.c[1] == .b) XCTAssertEqual(nestedStruct1.c[1], .b)
let nestedStruct2 = a.d[1] let nestedStruct2 = a.d[1]
#expect(nestedStruct2.a.reduce(0) { $0 + $1 } == -1) XCTAssertEqual(nestedStruct2.a.reduce(0) { $0 + $1 }, -1)
#expect(nestedStruct2.b == .b) XCTAssertEqual(nestedStruct2.b, .b)
#expect(nestedStruct2.c[0] == .b) XCTAssertEqual(nestedStruct2.c[0], .b)
#expect(nestedStruct2.c[1] == .a) XCTAssertEqual(nestedStruct2.c[1], .a)
#expect(nestedStruct2.d[0] == -0x1122334455667788) XCTAssertEqual(nestedStruct2.d[0], -0x1122334455667788)
#expect(nestedStruct2.d[1] == 0x1122334455667788) XCTAssertEqual(nestedStruct2.d[1], 0x1122334455667788)
#expect(a.mutate(b: 1000, at: 0) == true) XCTAssertTrue(a.mutate(b: 1000, at: 0))
#expect(a.mutate(b: 2000, at: 1) == true) XCTAssertTrue(a.mutate(b: 2000, at: 1))
#expect(nestedStruct2.mutate(c: .a, at: 0) == true) XCTAssertTrue(nestedStruct2.mutate(c: .a, at: 0))
#expect(nestedStruct2.mutate(c: .b, at: 1) == true) XCTAssertTrue(nestedStruct2.mutate(c: .b, at: 1))
#expect(nestedStruct2.c[0] == .a) XCTAssertEqual(nestedStruct2.c[0], .a)
#expect(nestedStruct2.c[1] == .b) XCTAssertEqual(nestedStruct2.c[1], .b)
#expect(nestedStruct2.mutate(d: 0, at: 0) == true) XCTAssertTrue(nestedStruct2.mutate(d: 0, at: 0))
#expect(nestedStruct2.mutate(d: 0, at: 1) == true) XCTAssertTrue(nestedStruct2.mutate(d: 0, at: 1))
#expect(nestedStruct2.d.reduce(0) { $0 + $1 } == 0) XCTAssertEqual(nestedStruct2.d.reduce(0) { $0 + $1 }, 0)
let nativeStruct = table.a?.d[1] let nativeStruct = table.a?.d[1]
#expect(nativeStruct?.c[0] == .a) XCTAssertEqual(nativeStruct?.c[0], .a)
#expect(nativeStruct?.c[1] == .b) XCTAssertEqual(nativeStruct?.c[1], .b)
#expect(nativeStruct?.d[0] == 0) XCTAssertEqual(nativeStruct?.d[0], 0)
#expect(nativeStruct?.d[1] == 0) XCTAssertEqual(nativeStruct?.d[1], 0)
#expect(a.mutate(b: 1, at: 0) == true) XCTAssertTrue(a.mutate(b: 1, at: 0))
#expect(a.mutate(b: 2, at: 1) == true) XCTAssertTrue(a.mutate(b: 2, at: 1))
#expect(nestedStruct2.mutate(c: .b, at: 0) == true) XCTAssertTrue(nestedStruct2.mutate(c: .b, at: 0))
#expect(nestedStruct2.mutate(c: .a, at: 1) == true) XCTAssertTrue(nestedStruct2.mutate(c: .a, at: 1))
#expect(nestedStruct2.mutate(d: -0x1122334455667788, at: 0) == true) XCTAssertTrue(nestedStruct2.mutate(d: -0x1122334455667788, at: 0))
#expect(nestedStruct2.mutate(d: 0x1122334455667788, at: 1) == true) XCTAssertTrue(nestedStruct2.mutate(d: 0x1122334455667788, at: 1))
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
private func createArrayTable() -> [UInt8] { private func createArrayTable() -> [UInt8] {
var builder = FlatBufferBuilder(initialSize: 1024) var builder = FlatBufferBuilder(initialSize: 1024)
@@ -246,3 +233,4 @@ extension InlineArray: @retroactive Equatable where Element: Equatable {
} }
#endif #endif
@@ -15,7 +15,7 @@
*/ */
import Foundation import Foundation
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
@@ -24,9 +24,8 @@ typealias Monster = MyGame_Example_Monster
typealias Vec3 = MyGame_Example_Vec3 typealias Vec3 = MyGame_Example_Vec3
typealias Stat = MyGame_Example_Stat typealias Stat = MyGame_Example_Stat
struct FlatBuffersMonsterWriterTests { class FlatBuffersMonsterWriterTests: XCTestCase {
@Test
func testData() { func testData() {
// swiftformat:disable all // swiftformat:disable all
let data = Data([ let data = Data([
@@ -48,13 +47,12 @@ struct FlatBuffersMonsterWriterTests {
readVerifiedMonster(fb: _data) readVerifiedMonster(fb: _data)
} }
@Test
func testReadFromOtherLanguages() { func testReadFromOtherLanguages() {
let path = { let path = {
#if os(macOS) #if os(macOS)
// Gets the current path of this test file then // Gets the current path of this test file then
// strips out the nested directories. // strips out the nested directories.
let filePath = URL(filePath: #filePath) let filePath = URL(filePath: #file)
.deletingLastPathComponent() .deletingLastPathComponent()
return filePath.absoluteString return filePath.absoluteString
#else #else
@@ -73,7 +71,6 @@ struct FlatBuffersMonsterWriterTests {
readVerifiedMonster(fb: _data) readVerifiedMonster(fb: _data)
} }
@Test
func testCreateMonsterData() { func testCreateMonsterData() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
var buffer = ByteBuffer(data: bytes.data) var buffer = ByteBuffer(data: bytes.data)
@@ -83,32 +80,30 @@ struct FlatBuffersMonsterWriterTests {
readMonster(monster: monster) readMonster(monster: monster)
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/8642"))
func testCreateMonsterResetTests() { func testCreateMonsterResetTests() {
var builder = createMonster(withPrefix: false) var builder = createMonster(withPrefix: false)
var buffer = ByteBuffer(data: builder.data) var buffer = ByteBuffer(data: builder.data)
let monster: MyGame_Example_Monster = getRoot(byteBuffer: &buffer) let monster: MyGame_Example_Monster = getRoot(byteBuffer: &buffer)
readMonster(monster: monster) readMonster(monster: monster)
builder.clear() builder.clear()
#expect(builder.capacity == 1) XCTAssertEqual(builder.capacity, 1)
#expect(builder.size == 0) XCTAssertEqual(builder.size, 0)
write(fbb: &builder, prefix: false) write(fbb: &builder, prefix: false)
var _buffer = ByteBuffer(data: builder.data) var _buffer = ByteBuffer(data: builder.data)
#expect(_buffer.capacity == 304) XCTAssertEqual(_buffer.capacity, 304)
let _monster: MyGame_Example_Monster = getRoot(byteBuffer: &_buffer) let _monster: MyGame_Example_Monster = getRoot(byteBuffer: &_buffer)
readMonster(monster: _monster) readMonster(monster: _monster)
builder.clear(keepingCapacity: true) builder.clear(keepingCapacity: true)
#expect(builder.capacity == 512) XCTAssertEqual(builder.capacity, 512)
#expect(builder.size == 0) XCTAssertEqual(builder.size, 0)
} }
@Test
func testCreateMonster() { func testCreateMonster() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -132,12 +127,11 @@ struct FlatBuffersMonsterWriterTests {
readMonster(monster: monster) readMonster(monster: monster)
} }
@Test
func testCreateMonsterResizedBuffer() { func testCreateMonsterResizedBuffer() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -156,12 +150,11 @@ struct FlatBuffersMonsterWriterTests {
readVerifiedMonster(fb: bytes.sizedBuffer) readVerifiedMonster(fb: bytes.sizedBuffer)
} }
@Test
func testCreateMonsterPrefixed() { func testCreateMonsterPrefixed() {
let bytes = createMonster(withPrefix: true) let bytes = createMonster(withPrefix: true)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -182,7 +175,6 @@ struct FlatBuffersMonsterWriterTests {
readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer)) readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer))
} }
@Test
func testCreateMonsterUsingCreateMonsterMethodWithNilPos() { func testCreateMonsterUsingCreateMonsterMethodWithNilPos() {
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Frodo") let name = fbb.create(string: "Frodo")
@@ -192,11 +184,10 @@ struct FlatBuffersMonsterWriterTests {
fbb.finish(offset: root) fbb.finish(offset: root)
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
#expect(newMonster.pos == nil) XCTAssertNil(newMonster.pos)
#expect(newMonster.name == "Frodo") XCTAssertEqual(newMonster.name, "Frodo")
} }
@Test
func testCreateMonsterUsingCreateMonsterMethodWithPosX() { func testCreateMonsterUsingCreateMonsterMethodWithPosX() {
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Barney") let name = fbb.create(string: "Barney")
@@ -216,11 +207,10 @@ struct FlatBuffersMonsterWriterTests {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
#expect(newMonster.pos!.x == 10) XCTAssertEqual(newMonster.pos!.x, 10)
#expect(newMonster.name == "Barney") XCTAssertEqual(newMonster.name, "Barney")
} }
@Test
func testReadMonsterFromUnsafePointerWithoutCopying() { func testReadMonsterFromUnsafePointerWithoutCopying() {
// swiftformat:disable all // swiftformat:disable all
var array: [UInt8] = [ var array: [UInt8] = [
@@ -252,7 +242,6 @@ struct FlatBuffersMonsterWriterTests {
readObjectApi(monster: unpacked) readObjectApi(monster: unpacked)
} }
@Test
func testArrayOfBools() { func testArrayOfBools() {
let boolArray = [false, true, false, true, false, true, false] let boolArray = [false, true, false, true, false, true, false]
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
@@ -268,41 +257,37 @@ struct FlatBuffersMonsterWriterTests {
let monster: Monster = getRoot(byteBuffer: &buffer) let monster: Monster = getRoot(byteBuffer: &buffer)
let values = monster.testarrayofbools let values = monster.testarrayofbools
#expect(boolArray.count == values.count) XCTAssertEqual(boolArray.count, values.count)
for (index, bool) in monster.testarrayofbools.enumerated() { for (index, bool) in monster.testarrayofbools.enumerated() {
#expect(bool == boolArray[index]) XCTAssertEqual(bool, boolArray[index])
} }
} }
func readVerifiedMonster(fb: ByteBuffer) { func readVerifiedMonster(fb: ByteBuffer) {
var byteBuffer = fb var byteBuffer = fb
do { XCTAssertNoThrow(
try readMonster( try readMonster(
monster: getCheckedRoot( monster: getCheckedRoot(
byteBuffer: &byteBuffer) as MyGame_Example_Monster) byteBuffer: &byteBuffer) as MyGame_Example_Monster))
} catch {
Issue.record(error)
}
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/8133"))
func testUnalignedRead() { func testUnalignedRead() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
let testAligned: () -> Bool = { let testAligned: () -> Bool = {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
var monster: Monster = getRoot(byteBuffer: &buffer) var monster: Monster = getRoot(byteBuffer: &buffer)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
#expect(testAligned() == true) XCTAssertEqual(testAligned(), true)
let testUnaligned: () -> Bool = { let testUnaligned: () -> Bool = {
var bytes: [UInt8] = [0x00] var bytes: [UInt8] = [0x00]
bytes.append(contentsOf: fbb.sizedByteArray) bytes.append(contentsOf: fbb.sizedByteArray)
return bytes.withUnsafeMutableBytes { ptr in return bytes.withUnsafeMutableBytes { ptr in
guard var baseAddress = ptr.baseAddress else { guard var baseAddress = ptr.baseAddress else {
Issue.record("Base pointer is not defined") XCTFail("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -311,14 +296,13 @@ struct FlatBuffersMonsterWriterTests {
assumingMemoryBound: unlignedPtr, assumingMemoryBound: unlignedPtr,
capacity: ptr.count - 1) capacity: ptr.count - 1)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
#expect(testUnaligned() == true) XCTAssertEqual(testUnaligned(), true)
} }
@Test
func testReadingRemovedSizeUnalignedBuffer() { func testReadingRemovedSizeUnalignedBuffer() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: true) let fbb = createMonster(withPrefix: true)
@@ -327,7 +311,7 @@ struct FlatBuffersMonsterWriterTests {
bytes.append(contentsOf: fbb.sizedByteArray) bytes.append(contentsOf: fbb.sizedByteArray)
return bytes.withUnsafeMutableBytes { ptr in return bytes.withUnsafeMutableBytes { ptr in
guard var baseAddress = ptr.baseAddress else { guard var baseAddress = ptr.baseAddress else {
Issue.record("Base pointer is not defined") XCTFail("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -337,34 +321,32 @@ struct FlatBuffersMonsterWriterTests {
capacity: ptr.count - 1) capacity: ptr.count - 1)
var newBuf = FlatBuffersUtils.removeSizePrefix(bb: bytes) var newBuf = FlatBuffersUtils.removeSizePrefix(bb: bytes)
var monster: Monster = getRoot(byteBuffer: &newBuf) var monster: Monster = getRoot(byteBuffer: &newBuf)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
#expect(testUnaligned() == true) XCTAssertEqual(testUnaligned(), true)
} }
@Test
func testCreateMessage() { func testCreateMessage() {
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
let byteBuffer = fbb.buffer let byteBuffer = fbb.buffer
let firstMessage = GRPCMessage<Monster>(byteBuffer: byteBuffer) let firstMessage = Message<Monster>(byteBuffer: byteBuffer)
firstMessage.withUnsafeReadableBytes { ptr in firstMessage.withUnsafeReadableBytes { ptr in
var bytes = ByteBuffer(contiguousBytes: ptr, count: ptr.count) var bytes = ByteBuffer(contiguousBytes: ptr, count: ptr.count)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
} }
let secondByteBuffer = fbb.sizedBuffer let secondByteBuffer = fbb.sizedBuffer
let secondMessage = GRPCMessage<Monster>(byteBuffer: secondByteBuffer) let secondMessage = Message<Monster>(byteBuffer: secondByteBuffer)
secondMessage.withUnsafeReadableBytes { ptr in secondMessage.withUnsafeReadableBytes { ptr in
var bytes = ByteBuffer(contiguousBytes: ptr, count: ptr.count) var bytes = ByteBuffer(contiguousBytes: ptr, count: ptr.count)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
} }
} }
@Test
func testForceRetainedObject() { func testForceRetainedObject() {
let byteBuffer = { let byteBuffer = {
// swiftformat:disable all // swiftformat:disable all
@@ -470,95 +452,95 @@ struct FlatBuffersMonsterWriterTests {
var fb = fb var fb = fb
let monster: Monster = getRoot(byteBuffer: &fb) let monster: Monster = getRoot(byteBuffer: &fb)
#expect(monster.mutate(mana: 10) == false) XCTAssertFalse(monster.mutate(mana: 10))
#expect(monster.testarrayoftables[0].name == "Barney") XCTAssertEqual(monster.testarrayoftables[0].name, "Barney")
#expect(monster.testarrayoftables[1].name == "Frodo") XCTAssertEqual(monster.testarrayoftables[1].name, "Frodo")
#expect(monster.testarrayoftables[2].name == "Wilma") XCTAssertEqual(monster.testarrayoftables[2].name, "Wilma")
// Example of searching for a table by the key // Example of searching for a table by the key
#expect(monster.testarrayoftablesBy(key: "Frodo") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Frodo"))
#expect(monster.testarrayoftablesBy(key: "Barney") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Barney"))
#expect(monster.testarrayoftablesBy(key: "Wilma") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Wilma"))
#expect(monster.testType == .monster) XCTAssertEqual(monster.testType, .monster)
#expect(monster.mutate(inventory: 1, at: 0) == true) XCTAssertEqual(monster.mutate(inventory: 1, at: 0), true)
#expect(monster.mutate(inventory: 2, at: 1) == true) XCTAssertEqual(monster.mutate(inventory: 2, at: 1), true)
#expect(monster.mutate(inventory: 3, at: 2) == true) XCTAssertEqual(monster.mutate(inventory: 3, at: 2), true)
#expect(monster.mutate(inventory: 4, at: 3) == true) XCTAssertEqual(monster.mutate(inventory: 4, at: 3), true)
#expect(monster.mutate(inventory: 5, at: 4) == true) XCTAssertEqual(monster.mutate(inventory: 5, at: 4), true)
for i in 0..<monster.inventory.count { for i in 0..<monster.inventory.count {
#expect(monster.inventory[i] == Byte(i + 1)) XCTAssertEqual(monster.inventory[i], Byte(i + 1))
} }
#expect(monster.mutate(inventory: 0, at: 0) == true) XCTAssertEqual(monster.mutate(inventory: 0, at: 0), true)
#expect(monster.mutate(inventory: 1, at: 1) == true) XCTAssertEqual(monster.mutate(inventory: 1, at: 1), true)
#expect(monster.mutate(inventory: 2, at: 2) == true) XCTAssertEqual(monster.mutate(inventory: 2, at: 2), true)
#expect(monster.mutate(inventory: 3, at: 3) == true) XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true)
#expect(monster.mutate(inventory: 4, at: 4) == true) XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true)
let vec = monster.mutablePos let vec = monster.mutablePos
#expect(vec?.x == 1) XCTAssertEqual(vec?.x, 1)
#expect(vec?.mutate(x: 55.0) == true) XCTAssertTrue(vec?.mutate(x: 55.0) ?? false)
#expect(vec?.mutate(test1: 55) == true) XCTAssertTrue(vec?.mutate(test1: 55) ?? false)
#expect(vec?.x == 55.0) XCTAssertEqual(vec?.x, 55.0)
#expect(vec?.test1 == 55.0) XCTAssertEqual(vec?.test1, 55.0)
#expect(vec?.mutate(x: 1) == true) XCTAssertTrue(vec?.mutate(x: 1) ?? false)
#expect(vec?.x == 1) XCTAssertEqual(vec?.x, 1)
#expect(vec?.mutate(test1: 3) == true) XCTAssertTrue(vec?.mutate(test1: 3) ?? false)
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
let orignalValues = mutableTest4[0].a let orignalValues = mutableTest4[0].a
#expect(mutableTest4[0].mutate(a: 100) == true) XCTAssertEqual(mutableTest4[0].mutate(a: 100), true)
#expect(monster.test4[0].a != orignalValues) XCTAssertNotEqual(monster.test4[0].a, orignalValues)
#expect(monster.test4[0].a == 100) XCTAssertEqual(monster.test4[0].a, 100)
#expect(mutableTest4[0].mutate(a: orignalValues) == true) XCTAssertEqual(mutableTest4[0].mutate(a: orignalValues), true)
} }
func readFlatbufferMonster(monster: inout MyGame_Example_Monster) { func readFlatbufferMonster(monster: inout MyGame_Example_Monster) {
#expect(monster.hp == 80) XCTAssertEqual(monster.hp, 80)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.name == "MyMonster") XCTAssertEqual(monster.name, "MyMonster")
let pos = monster.pos let pos = monster.pos
#expect(pos?.x == 1) XCTAssertEqual(pos?.x, 1)
#expect(pos?.y == 2) XCTAssertEqual(pos?.y, 2)
#expect(pos?.z == 3) XCTAssertEqual(pos?.z, 3)
#expect(pos?.test1 == 3) XCTAssertEqual(pos?.test1, 3)
#expect(pos?.test2 == .green) XCTAssertEqual(pos?.test2, .green)
let test = pos?.test3 let test = pos?.test3
#expect(test?.a == 5) XCTAssertEqual(test?.a, 5)
#expect(test?.b == 6) XCTAssertEqual(test?.b, 6)
#expect(monster.testType == .monster) XCTAssertEqual(monster.testType, .monster)
let monster2 = monster.test(type: Monster.self) let monster2 = monster.test(type: Monster.self)
#expect(monster2?.name == "Fred") XCTAssertEqual(monster2?.name, "Fred")
#expect(monster.mutate(mana: 10) == false) XCTAssertEqual(monster.mutate(mana: 10), false)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.inventory.count == 5) XCTAssertEqual(monster.inventory.count, 5)
var sum: Byte = 0 var sum: Byte = 0
for inventory in monster.inventory { for inventory in monster.inventory {
sum += inventory sum += inventory
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
monster.withUnsafePointerToInventory { ptr, count in monster.withUnsafePointerToInventory { ptr, count in
var sum: UInt8 = 0 var sum: UInt8 = 0
for pointee in ptr.startIndex..<ptr.endIndex { for pointee in ptr.startIndex..<ptr.endIndex {
sum += ptr[pointee] sum += ptr[pointee]
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
} }
#expect(monster.test4.count == 2) XCTAssertEqual(monster.test4.count, 2)
let test4 = monster.test4 let test4 = monster.test4
var sum0 = 0 var sum0 = 0
for test0 in test4 { for test0 in test4 {
sum0 += Int(test0.a) + Int(test0.b) sum0 += Int(test0.a) + Int(test0.b)
} }
#expect(sum0 == 100) XCTAssertEqual(sum0, 100)
monster.withUnsafePointerToTest4 { ptr, count in monster.withUnsafePointerToTest4 { ptr, count in
guard let ptr = ptr.baseAddress else { return } guard let ptr = ptr.baseAddress else { return }
@@ -574,7 +556,7 @@ struct FlatBuffersMonsterWriterTests {
pointerSum += Int(bindedMemory[pointee].a) + pointerSum += Int(bindedMemory[pointee].a) +
Int(bindedMemory[pointee].b) Int(bindedMemory[pointee].b)
} }
#expect(pointerSum == 100) XCTAssertEqual(pointerSum, 100)
} }
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
@@ -582,84 +564,87 @@ struct FlatBuffersMonsterWriterTests {
for test0 in mutableTest4 { for test0 in mutableTest4 {
sum2 += Int(test0.a) + Int(test0.b) sum2 += Int(test0.a) + Int(test0.b)
} }
#expect(sum2 == 100) XCTAssertEqual(sum2, 100)
let stringArray = monster.testarrayofstring let stringArray = monster.testarrayofstring
#expect(stringArray.count == 2) XCTAssertEqual(stringArray.count, 2)
#expect(stringArray[0] == "test1") XCTAssertEqual(stringArray[0], "test1")
#expect(stringArray[1] == "test2") XCTAssertEqual(stringArray[1], "test2")
#expect(monster.testbool == true) XCTAssertEqual(monster.testbool, true)
let array = monster.nameSegmentArray let array = monster.nameSegmentArray
#expect(String(bytes: array ?? [], encoding: .utf8) == "MyMonster") XCTAssertEqual(String(bytes: array ?? [], encoding: .utf8), "MyMonster")
if 0 == monster.testarrayofbools.count { if 0 == monster.testarrayofbools.count {
#expect(monster.testarrayofbools.isEmpty == true) XCTAssertEqual(monster.testarrayofbools.isEmpty, true)
} else { } else {
#expect(monster.testarrayofbools.isEmpty == false) XCTAssertEqual(monster.testarrayofbools.isEmpty, false)
} }
} }
func readObjectApi(monster: MyGame_Example_MonsterT) { func readObjectApi(monster: MyGame_Example_MonsterT) {
#expect(monster.hp == 80) XCTAssertEqual(monster.hp, 80)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.name == "MyMonster") XCTAssertEqual(monster.name, "MyMonster")
let pos = monster.pos let pos = monster.pos
#expect(pos?.x == 1) XCTAssertEqual(pos?.x, 1)
#expect(pos?.y == 2) XCTAssertEqual(pos?.y, 2)
#expect(pos?.z == 3) XCTAssertEqual(pos?.z, 3)
#expect(pos?.test1 == 3) XCTAssertEqual(pos?.test1, 3)
#expect(pos?.test2 == .green) XCTAssertEqual(pos?.test2, .green)
let test = pos?.test3 let test = pos?.test3
#expect(test?.a == 5) XCTAssertEqual(test?.a, 5)
#expect(test?.b == 6) XCTAssertEqual(test?.b, 6)
let monster2 = monster.test?.value as? MyGame_Example_MonsterT let monster2 = monster.test?.value as? MyGame_Example_MonsterT
#expect(monster2?.name == "Fred") XCTAssertEqual(monster2?.name, "Fred")
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
monster.mana = 10 monster.mana = 10
#expect(monster.mana == 10) XCTAssertEqual(monster.mana, 10)
monster.mana = 150 monster.mana = 150
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.inventory.count == 5) XCTAssertEqual(monster.inventory.count, 5)
var sum: Byte = 0 var sum: Byte = 0
for i in monster.inventory { for i in monster.inventory {
sum += i sum += i
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
#expect(monster.test4.count == 2) XCTAssertEqual(monster.test4.count, 2)
var sum0 = 0 var sum0 = 0
for test in monster.test4 { for test in monster.test4 {
sum0 += Int(test.a) + Int(test.b) sum0 += Int(test.a) + Int(test.b)
} }
#expect(sum0 == 100) XCTAssertEqual(sum0, 100)
#expect(monster.testbool == true) XCTAssertEqual(monster.testbool, true)
} }
@Test func testEncoding() {
func testEncoding() throws {
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
var sizedBuffer = fbb.sizedBuffer var sizedBuffer = fbb.sizedBuffer
struct Test: Decodable { do {
struct Pos: Decodable { struct Test: Decodable {
let x, y, z: Int struct Pos: Decodable {
let x, y, z: Int
}
let hp: Int
let inventory: [UInt8]
let name: String
let pos: Pos
} }
let hp: Int let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer)
let inventory: [UInt8] let encoder = JSONEncoder()
let name: String encoder.keyEncodingStrategy = .convertToSnakeCase
let pos: Pos let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
XCTAssertEqual(value.name, "MyMonster")
XCTAssertEqual(value.pos.x, 1)
XCTAssertEqual(value.pos.y, 2)
XCTAssertEqual(value.pos.z, 3)
} catch {
XCTFail(error.localizedDescription)
} }
let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
#expect(value.name == "MyMonster")
#expect(value.pos.x == 1)
#expect(value.pos.y == 2)
#expect(value.pos.z == 3)
} }
var jsonData: String { var jsonData: String {
@@ -668,7 +653,6 @@ struct FlatBuffersMonsterWriterTests {
""" """
} }
@Test
func testContiguousBytes() { func testContiguousBytes() {
let byteArray: [UInt8] = [3, 1, 4, 1, 5, 9] let byteArray: [UInt8] = [3, 1, 4, 1, 5, 9]
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
@@ -686,7 +670,7 @@ struct FlatBuffersMonsterWriterTests {
monster.withUnsafePointerToInventory { ptr, count in monster.withUnsafePointerToInventory { ptr, count in
let array = Array(ptr) let array = Array(ptr)
for (index, value) in values.enumerated() { for (index, value) in values.enumerated() {
#expect(array[index] == value) XCTAssertEqual(array[index], value)
} }
} }
} }
@@ -14,59 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
import Foundation import XCTest
import Testing
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersNanInfTests { final class FlatBuffersNanInfTests: XCTestCase {
@Test
func testInfNanBinary() {
let fbb = createTestTable()
let data = fbb.sizedByteArray
var buffer = ByteBuffer(bytes: data)
let table: Swift_Tests_NanInfTable = getRoot(byteBuffer: &buffer)
#expect(table.defaultNan.isNaN)
#expect(table.defaultInf == .infinity)
#expect(table.defaultNinf == -.infinity)
#expect(table.valueNan.isNaN)
#expect(table.valueInf == .infinity)
#expect(table.valueNinf == -.infinity)
#expect(table.value == 100.0)
}
@Test
func testInfNanJSON() throws {
let fbb = createTestTable()
var bb = fbb.sizedBuffer
struct Test: Decodable {
let valueInf: Double
let value: Int
let valueNan: Double
let valueNinf: Double
}
let reader: Swift_Tests_NanInfTable = try getCheckedRoot(byteBuffer: &bb)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.nonConformingFloatEncodingStrategy =
.convertToString(
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.nonConformingFloatDecodingStrategy = .convertFromString(
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
#expect(value.value == 100)
#expect(value.valueInf == .infinity)
#expect(value.valueNinf == -.infinity)
}
func createTestTable() -> FlatBufferBuilder { func createTestTable() -> FlatBufferBuilder {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
@@ -79,4 +31,54 @@ struct FlatBuffersNanInfTests {
fbb.finish(offset: msg) fbb.finish(offset: msg)
return fbb return fbb
} }
func testInfNanBinary() {
let fbb = createTestTable()
let data = fbb.sizedByteArray
var buffer = ByteBuffer(bytes: data)
let table: Swift_Tests_NanInfTable = getRoot(byteBuffer: &buffer)
XCTAssert(table.defaultNan.isNaN)
XCTAssertEqual(table.defaultInf, .infinity)
XCTAssertEqual(table.defaultNinf, -.infinity)
XCTAssert(table.valueNan.isNaN)
XCTAssertEqual(table.valueInf, .infinity)
XCTAssertEqual(table.valueNinf, -.infinity)
XCTAssertEqual(table.value, 100.0)
}
func testInfNanJSON() {
let fbb = createTestTable()
var bb = fbb.sizedBuffer
do {
struct Test: Decodable {
let valueInf: Double
let value: Int
let valueNan: Double
let valueNinf: Double
}
let reader: Swift_Tests_NanInfTable = try getCheckedRoot(byteBuffer: &bb)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.nonConformingFloatEncodingStrategy =
.convertToString(
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.nonConformingFloatDecodingStrategy = .convertFromString(
positiveInfinity: "inf",
negativeInfinity: "-inf",
nan: "nan")
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
XCTAssertEqual(value.value, 100)
XCTAssertEqual(value.valueInf, .infinity)
XCTAssertEqual(value.valueNinf, -.infinity)
} catch {
XCTFail(error.localizedDescription)
}
}
} }
@@ -14,13 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersStructsTests { final class FlatBuffersStructsTests: XCTestCase {
@Test
func testWritingAndMutatingBools() { func testWritingAndMutatingBools() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
let start = TestMutatingBool.startTestMutatingBool(&fbb) let start = TestMutatingBool.startTestMutatingBool(&fbb)
@@ -31,11 +30,11 @@ struct FlatBuffersStructsTests {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let testMutatingBool: TestMutatingBool = getRoot(byteBuffer: &buffer) let testMutatingBool: TestMutatingBool = getRoot(byteBuffer: &buffer)
let property = testMutatingBool.mutableB let property = testMutatingBool.mutableB
#expect(property?.property == false) XCTAssertEqual(property?.property, false)
property?.mutate(property: false) property?.mutate(property: false)
#expect(property?.property == false) XCTAssertEqual(property?.property, false)
property?.mutate(property: true) property?.mutate(property: true)
#expect(property?.property == true) XCTAssertEqual(property?.property, true)
} }
} }
@@ -14,49 +14,44 @@
* limitations under the License. * limitations under the License.
*/ */
import Testing import XCTest
@testable import Common @testable import Common
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersTests { final class FlatBuffersTests: XCTestCase {
let country = "Norway" let country = "Norway"
@Test func testEndian() { XCTAssertEqual(isLitteEndian, true) }
func testEndian() { #expect(isLitteEndian == true) }
@Test
func testOffset() { func testOffset() {
let o = Offset() let o = Offset()
let b = Offset(offset: 1) let b = Offset(offset: 1)
#expect(o.isEmpty == true) XCTAssertEqual(o.isEmpty, true)
#expect(b.isEmpty == false) XCTAssertEqual(b.isEmpty, false)
} }
@Test
func testCreateString() { func testCreateString() {
let helloWorld = "Hello, world!" let helloWorld = "Hello, world!"
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
#expect(b.create(string: country).o == 12) XCTAssertEqual(b.create(string: country).o, 12)
#expect(b.create(string: helloWorld).o == 32) XCTAssertEqual(b.create(string: helloWorld).o, 32)
b.clear() b.clear()
#expect(b.create(string: helloWorld).o == 20) XCTAssertEqual(b.create(string: helloWorld).o, 20)
#expect(b.create(string: country).o == 32) XCTAssertEqual(b.create(string: country).o, 32)
b.clear() b.clear()
#expect(b.create(string: String(repeating: "a", count: 257)).o == 264) XCTAssertEqual(b.create(string: String(repeating: "a", count: 257)).o, 264)
} }
@Test
func testStartTable() { func testStartTable() {
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
_ = b.startTable(with: 0) XCTAssertNoThrow(b.startTable(with: 0))
b.clear() b.clear()
#expect(b.create(string: country).o == 12) XCTAssertEqual(b.create(string: country).o, 12)
#expect(b.startTable(with: 0) == 12) XCTAssertEqual(b.startTable(with: 0), 12)
} }
@Test
func testCreateFinish() { func testCreateFinish() {
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
let countryOff = Country.createCountry( let countryOff = Country.createCountry(
@@ -71,10 +66,9 @@ struct FlatBuffersTests {
200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0,
] ]
// swiftformat:enable all // swiftformat:enable all
#expect(b.sizedByteArray == v) XCTAssertEqual(b.sizedByteArray, v)
} }
@Test
func testCreateFinishWithPrefix() { func testCreateFinishWithPrefix() {
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
let countryOff = Country.createCountry( let countryOff = Country.createCountry(
@@ -89,10 +83,9 @@ struct FlatBuffersTests {
100, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0,
] ]
// swiftformat:enable all // swiftformat:enable all
#expect(b.sizedByteArray == v) XCTAssertEqual(b.sizedByteArray, v)
} }
@Test
func testReadCountry() { func testReadCountry() {
// swiftformat:disable all // swiftformat:disable all
let v: [UInt8] = [ let v: [UInt8] = [
@@ -102,20 +95,18 @@ struct FlatBuffersTests {
// swiftformat:enable all // swiftformat:enable all
let buffer = ByteBuffer(bytes: v) let buffer = ByteBuffer(bytes: v)
let c = Country.getRootAsCountry(buffer) let c = Country.getRootAsCountry(buffer)
#expect(c.lan == 100) XCTAssertEqual(c.lan, 100)
#expect(c.log == 200) XCTAssertEqual(c.log, 200)
#expect(c.nameVector == [78, 111, 114, 119, 97, 121]) XCTAssertEqual(c.nameVector, [78, 111, 114, 119, 97, 121])
#expect(c.name == country) XCTAssertEqual(c.name, country)
} }
@Test
func testWriteNullableStrings() { func testWriteNullableStrings() {
var b = FlatBufferBuilder() var b = FlatBufferBuilder()
#expect(b.create(string: nil).isEmpty) XCTAssertTrue(b.create(string: nil).isEmpty)
#expect(b.createShared(string: nil).isEmpty) XCTAssertTrue(b.createShared(string: nil).isEmpty)
} }
@Test
func testWriteOptionalValues() { func testWriteOptionalValues() {
var b = FlatBufferBuilder() var b = FlatBufferBuilder()
let root = optional_scalars_ScalarStuff.createScalarStuff( let root = optional_scalars_ScalarStuff.createScalarStuff(
@@ -130,17 +121,16 @@ struct FlatBuffersTests {
b.finish(offset: root) b.finish(offset: root)
var buffer = b.sizedBuffer var buffer = b.sizedBuffer
let scalarTable: optional_scalars_ScalarStuff = getRoot(byteBuffer: &buffer) let scalarTable: optional_scalars_ScalarStuff = getRoot(byteBuffer: &buffer)
#expect(scalarTable.justI8 == 80) XCTAssertEqual(scalarTable.justI8, 80)
#expect(scalarTable.maybeI8 == nil) XCTAssertNil(scalarTable.maybeI8)
#expect(scalarTable.maybeBool == true) XCTAssertEqual(scalarTable.maybeBool, true)
#expect(scalarTable.defaultI8 == 42) XCTAssertEqual(scalarTable.defaultI8, 42)
#expect(scalarTable.justU8 == 100) XCTAssertEqual(scalarTable.justU8, 100)
#expect(scalarTable.maybeU8 == 10) XCTAssertEqual(scalarTable.maybeU8, 10)
#expect(scalarTable.justEnum == .one) XCTAssertEqual(scalarTable.justEnum, .one)
#expect(scalarTable.maybeEnum == nil) XCTAssertNil(scalarTable.maybeEnum)
} }
@Test
func testAlignmentCrash() { func testAlignmentCrash() {
var builder = FlatBufferBuilder(initialSize: 256) var builder = FlatBufferBuilder(initialSize: 256)
@@ -14,14 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
import Foundation import XCTest
import Testing
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersUnionTests { final class FlatBuffersUnionTests: XCTestCase {
@Test
func testCreateMonstor() { func testCreateMonstor() {
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
@@ -38,8 +36,8 @@ struct FlatBuffersUnionTests {
b.finish(offset: root) b.finish(offset: root)
let buffer = b.sizedByteArray let buffer = b.sizedByteArray
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
buffer == buffer,
[ [
16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 8, 0, 7, 0, 12, 0, 10, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 20, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 8, 0, 7, 0, 12, 0, 10, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 20,
0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 12, 0, 8, 0, 6, 0, 8, 0, 0, 0, 0, 0, 5, 0, 4, 0, 0,
@@ -47,16 +45,15 @@ struct FlatBuffersUnionTests {
]) ])
// swiftformat:enable all // swiftformat:enable all
let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer)) let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer))
#expect(monster.weapon(at: 0)?.dmg == dmg) XCTAssertEqual(monster.weapon(at: 0)?.dmg, dmg)
#expect(monster.weapon(at: 0)?.name == str) XCTAssertEqual(monster.weapon(at: 0)?.name, str)
#expect(monster.weapon(at: 0)?.nameVector == [65, 120, 101]) XCTAssertEqual(monster.weapon(at: 0)?.nameVector, [65, 120, 101])
let p: Weapon? = monster.equiped() let p: Weapon? = monster.equiped()
#expect(p?.dmg == dmg) XCTAssertEqual(p?.dmg, dmg)
#expect(p?.name == str) XCTAssertEqual(p?.name, str)
#expect(p?.nameVector == [65, 120, 101]) XCTAssertEqual(p?.nameVector, [65, 120, 101])
} }
@Test
func testEndTableFinish() { func testEndTableFinish() {
var builder = FlatBufferBuilder(initialSize: 20) var builder = FlatBufferBuilder(initialSize: 20)
let sword = builder.create(string: "Sword") let sword = builder.create(string: "Sword")
@@ -87,8 +84,8 @@ struct FlatBuffersUnionTests {
path: path) path: path)
builder.finish(offset: orc) builder.finish(offset: orc)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
builder.sizedByteArray == builder.sizedByteArray,
[ [
32, 0, 0, 0, 0, 0, 26, 0, 48, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15, 32, 0, 0, 0, 0, 0, 26, 0, 48, 0, 36, 0, 0, 0, 34, 0, 28, 0, 0, 0, 24, 0, 23, 0, 16, 0, 15,
0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 4, 0, 26, 0, 0, 0, 44, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0,
@@ -102,7 +99,6 @@ struct FlatBuffersUnionTests {
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testEnumVector() { func testEnumVector() {
let vectorOfEnums: [ColorsNameSpace.RGB] = [.blue, .green] let vectorOfEnums: [ColorsNameSpace.RGB] = [.blue, .green]
@@ -113,8 +109,8 @@ struct FlatBuffersUnionTests {
let end = ColorsNameSpace.Monster.endMonster(&builder, start: start) let end = ColorsNameSpace.Monster.endMonster(&builder, start: start)
builder.finish(offset: end) builder.finish(offset: end)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
builder.sizedByteArray == builder.sizedByteArray,
[ [
12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0,
0, 0, 0, 0,
@@ -122,13 +118,12 @@ struct FlatBuffersUnionTests {
// swiftformat:enable all // swiftformat:enable all
let monster = ColorsNameSpace.Monster let monster = ColorsNameSpace.Monster
.getRootAsMonster(bb: builder.sizedBuffer) .getRootAsMonster(bb: builder.sizedBuffer)
#expect(monster.colorsCount == 2) XCTAssertEqual(monster.colorsCount, 2)
let colors = monster.colors let colors = monster.colors
#expect(colors[0] == .blue) XCTAssertEqual(colors[0], .blue)
#expect(colors[1] == .green) XCTAssertEqual(colors[1], .green)
} }
@Test
func testUnionVector() { func testUnionVector() {
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -154,30 +149,30 @@ struct FlatBuffersUnionTests {
var buffer = fb.sizedBuffer var buffer = fb.sizedBuffer
let movie: Movie = getRoot(byteBuffer: &buffer) let movie: Movie = getRoot(byteBuffer: &buffer)
#expect(movie.charactersType.count == characterType.count) XCTAssertEqual(movie.charactersType.count, characterType.count)
#expect(movie.characters.count == characters.count) XCTAssertEqual(movie.characters.count, characters.count)
let bufferCharactersType = movie.charactersType let bufferCharactersType = movie.charactersType
for (index, element) in bufferCharactersType.enumerated() { for (index, element) in bufferCharactersType.enumerated() {
#expect(element == characterType[index]) XCTAssertEqual(element, characterType[index])
} }
#expect( XCTAssertEqual(
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead == movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
7) 7)
#expect( XCTAssertEqual(
movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage == movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage,
swordDmg) swordDmg)
#expect( XCTAssertEqual(
movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead == movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead,
2) 2)
var objc: MovieT? = movie.unpack() var objc: MovieT? = movie.unpack()
#expect( XCTAssertEqual(
movie.charactersType.count == objc?.characters.count ?? 0) movie.charactersType.count, objc?.characters.count ?? 0)
#expect( XCTAssertEqual(
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead == movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
(objc?.characters[0]?.value as? BookReader)?.booksRead) (objc?.characters[0]?.value as? BookReader)?.booksRead)
fb.clear() fb.clear()
let newMovie = Movie.pack(&fb, obj: &objc) let newMovie = Movie.pack(&fb, obj: &objc)
fb.finish(offset: newMovie) fb.finish(offset: newMovie)
@@ -185,18 +180,17 @@ struct FlatBuffersUnionTests {
var _buffer = fb.sizedBuffer var _buffer = fb.sizedBuffer
let packedMovie: Movie = getRoot(byteBuffer: &_buffer) let packedMovie: Movie = getRoot(byteBuffer: &_buffer)
#expect( XCTAssertEqual(
packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead == packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead) movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead)
#expect( XCTAssertEqual(
packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage == packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage,
movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage) movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage)
#expect( XCTAssertEqual(
packedMovie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead == packedMovie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead,
movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead) movie.characters(at: 2, type: BookReader_Mutable.self)?.booksRead)
} }
@Test
func testStringUnion() { func testStringUnion() {
let string = "Awesome \\\\t\t\nstring!" let string = "Awesome \\\\t\t\nstring!"
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -220,31 +214,30 @@ struct FlatBuffersUnionTests {
var buffer = fb.sizedBuffer var buffer = fb.sizedBuffer
let movie: Movie = getRoot(byteBuffer: &buffer) let movie: Movie = getRoot(byteBuffer: &buffer)
#expect(movie.mainCharacter(type: String.self) == string) XCTAssertEqual(movie.mainCharacter(type: String.self), string)
#expect( XCTAssertEqual(
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead == movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
7) 7)
#expect(movie.characters(at: 1, type: String.self) == string) XCTAssertEqual(movie.characters(at: 1, type: String.self), string)
var objc: MovieT? = movie.unpack() var objc: MovieT? = movie.unpack()
#expect(objc?.mainCharacter?.value as? String == string) XCTAssertEqual(objc?.mainCharacter?.value as? String, string)
#expect((objc?.characters[0]?.value as? BookReader)?.booksRead == 7) XCTAssertEqual((objc?.characters[0]?.value as? BookReader)?.booksRead, 7)
#expect(objc?.characters[1]?.value as? String == string) XCTAssertEqual(objc?.characters[1]?.value as? String, string)
fb.clear() fb.clear()
let newMovie = Movie.pack(&fb, obj: &objc) let newMovie = Movie.pack(&fb, obj: &objc)
fb.finish(offset: newMovie) fb.finish(offset: newMovie)
var _buffer = fb.sizedBuffer var _buffer = fb.sizedBuffer
let packedMovie: Movie = getRoot(byteBuffer: &_buffer) let packedMovie: Movie = getRoot(byteBuffer: &_buffer)
#expect(packedMovie.mainCharacter(type: String.self) == string) XCTAssertEqual(packedMovie.mainCharacter(type: String.self), string)
#expect( XCTAssertEqual(
packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead == packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead,
7) 7)
#expect(packedMovie.characters(at: 1, type: String.self) == string) XCTAssertEqual(packedMovie.characters(at: 1, type: String.self), string)
} }
@Test func testEncoding() {
func testEncoding() throws {
let string = "Awesome \\\\t\t\nstring!" let string = "Awesome \\\\t\t\nstring!"
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -272,12 +265,16 @@ struct FlatBuffersUnionTests {
Movie.finish(&fb, end: end) Movie.finish(&fb, end: end)
var sizedBuffer = fb.sizedBuffer var sizedBuffer = fb.sizedBuffer
let reader: Movie = try getCheckedRoot(byteBuffer: &sizedBuffer) do {
let encoder = JSONEncoder() let reader: Movie = try getCheckedRoot(byteBuffer: &sizedBuffer)
encoder.keyEncodingStrategy = .convertToSnakeCase let encoder = JSONEncoder()
encoder.outputFormatting = [.sortedKeys] encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(reader) encoder.outputFormatting = [.sortedKeys]
#expect(String(data: data, encoding: .utf8) == jsonData) let data = try encoder.encode(reader)
XCTAssertEqual(String(data: data, encoding: .utf8), jsonData)
} catch {
XCTFail(error.localizedDescription)
}
} }
var jsonData: String { var jsonData: String {
@@ -14,13 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersVectors { final class FlatBuffersVectors: XCTestCase {
@Test
func testCreatingTwoCountries() { func testCreatingTwoCountries() {
let norway = "Norway" let norway = "Norway"
let denmark = "Denmark" let denmark = "Denmark"
@@ -41,8 +40,8 @@ struct FlatBuffersVectors {
let vectorOffset = b.createVector(ofOffsets: vector) let vectorOffset = b.createVector(ofOffsets: vector)
b.finish(offset: vectorOffset) b.finish(offset: vectorOffset)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
b.sizedByteArray == b.sizedByteArray,
[ [
4, 0, 0, 0, 2, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 18, 0, 4, 0, 8, 0, 12, 0, 10, 4, 0, 0, 0, 2, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 18, 0, 4, 0, 8, 0, 12, 0, 10,
0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 200, 0, 0, 0, 0, 0, 10, 0, 16, 0, 4, 0, 8, 0, 12, 0, 10,
@@ -52,20 +51,18 @@ struct FlatBuffersVectors {
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testCreateIntArray() { func testCreateIntArray() {
let numbers: [Int32] = [1, 2, 3, 4, 5] let numbers: [Int32] = [1, 2, 3, 4, 5]
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
let o = b.createVector(numbers, size: numbers.count) let o = b.createVector(numbers, size: numbers.count)
b.finish(offset: o) b.finish(offset: o)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
b.sizedByteArray == b.sizedByteArray,
[4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0]) [4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0])
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testCreateStructArray() { func testCreateStructArray() {
struct Vec: NativeStruct { struct Vec: NativeStruct {
let x, y, z: Float32 let x, y, z: Float32
@@ -79,8 +76,8 @@ struct FlatBuffersVectors {
let o = b.createVector(ofStructs: vector) let o = b.createVector(ofStructs: vector)
b.finish(offset: o) b.finish(offset: o)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
b.sizedByteArray == b.sizedByteArray,
[ [
4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160,
64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65, 0, 0, 16, 65, 64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65, 0, 0, 16, 65,
@@ -88,31 +85,28 @@ struct FlatBuffersVectors {
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testCreateEmptyIntArray() { func testCreateEmptyIntArray() {
let numbers: [Int32] = [] let numbers: [Int32] = []
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
let o = b.createVector(numbers, size: numbers.count) let o = b.createVector(numbers, size: numbers.count)
b.finish(offset: o) b.finish(offset: o)
#expect(b.sizedByteArray == [4, 0, 0, 0, 0, 0, 0, 0]) XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 0, 0, 0, 0])
} }
@Test
func testCreateVectorOfStrings() { func testCreateVectorOfStrings() {
let strs = ["Denmark", "Norway"] let strs = ["Denmark", "Norway"]
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
let o = b.createVector(ofStrings: strs) let o = b.createVector(ofStrings: strs)
b.finish(offset: o) b.finish(offset: o)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
b.sizedByteArray == b.sizedByteArray,
[ [
4, 0, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 4, 0, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0,
0, 7, 0, 0, 0, 68, 101, 110, 109, 97, 114, 107, 0, 0, 7, 0, 0, 0, 68, 101, 110, 109, 97, 114, 107, 0,
]) ])
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testCreateSharedStringVector() { func testCreateSharedStringVector() {
let norway = "Norway" let norway = "Norway"
let denmark = "Denmark" let denmark = "Denmark"
@@ -125,8 +119,8 @@ struct FlatBuffersVectors {
let end = b.createVector(ofOffsets: v) let end = b.createVector(ofOffsets: v)
b.finish(offset: end) b.finish(offset: end)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
b.sizedByteArray == b.sizedByteArray,
[ [
4, 0, 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 68, 4, 0, 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 68,
101, 110, 109, 97, 114, 107, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0, 101, 110, 109, 97, 114, 107, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0,
@@ -134,7 +128,6 @@ struct FlatBuffersVectors {
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testReadInt32Array() { func testReadInt32Array() {
let data: [Int32] = [1, 2, 3, 4, 5] let data: [Int32] = [1, 2, 3, 4, 5]
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
@@ -143,11 +136,10 @@ struct FlatBuffersVectors {
b.finish(offset: end) b.finish(offset: end)
let number = Numbers.getRootAsNumbers(ByteBuffer(bytes: b.sizedByteArray)) let number = Numbers.getRootAsNumbers(ByteBuffer(bytes: b.sizedByteArray))
for (index, num) in number.vArrayInt32.enumerated() { for (index, num) in number.vArrayInt32.enumerated() {
#expect(num == data[index]) XCTAssertEqual(num, data[index])
} }
} }
@Test
func testReadDoubleArray() { func testReadDoubleArray() {
let data: [Double] = [1, 2, 3, 4, 5] let data: [Double] = [1, 2, 3, 4, 5]
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
@@ -156,11 +148,10 @@ struct FlatBuffersVectors {
b.finish(offset: end) b.finish(offset: end)
let number = Numbers.getRootAsNumbers(ByteBuffer(bytes: b.sizedByteArray)) let number = Numbers.getRootAsNumbers(ByteBuffer(bytes: b.sizedByteArray))
for (index, num) in number.vArrayDouble.enumerated() { for (index, num) in number.vArrayDouble.enumerated() {
#expect(num == data[index]) XCTAssertEqual(num, data[index])
} }
} }
@Test
func testHasForArray() { func testHasForArray() {
var builder = FlatBufferBuilder(initialSize: 20) var builder = FlatBufferBuilder(initialSize: 20)
let emptyVector = [UInt8]() let emptyVector = [UInt8]()
@@ -175,14 +166,14 @@ struct FlatBuffersVectors {
var byteBuffer = ByteBuffer(bytes: builder.sizedByteArray) var byteBuffer = ByteBuffer(bytes: builder.sizedByteArray)
let msg: Swift_Tests_Vectors = getRoot(byteBuffer: &byteBuffer) let msg: Swift_Tests_Vectors = getRoot(byteBuffer: &byteBuffer)
#expect(msg.none_.isEmpty == true) XCTAssertEqual(msg.none_.isEmpty, true)
#expect(msg.empty.isEmpty == true) XCTAssertEqual(msg.empty.isEmpty, true)
#expect(msg.empty.count == 0) XCTAssertEqual(msg.empty.count, 0)
#expect(msg.array.isEmpty == false) XCTAssertEqual(msg.array.isEmpty, false)
#expect(msg.array.count == 3) XCTAssertEqual(msg.array.count, 3)
for i in msg.array.startIndex..<msg.array.endIndex { for i in msg.array.startIndex..<msg.array.endIndex {
#expect(msg.array[i] == 1 + UInt64(i)) XCTAssertEqual(msg.array[i], 1 + UInt64(i))
} }
let array = msg.withUnsafePointerToArray { ptr, count in let array = msg.withUnsafePointerToArray { ptr, count in
@@ -194,7 +185,7 @@ struct FlatBuffersVectors {
return Array(ptr) return Array(ptr)
} }
#expect(array == [1, 2, 3]) XCTAssertEqual(array, [1, 2, 3])
} }
} }
@@ -14,15 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersDoubleTests { final class FlatBuffersDoubleTests: XCTestCase {
let country = "Norway" let country = "Norway"
@Test
func testCreateFinish() { func testCreateFinish() {
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
let countryOff = CountryDouble.createCountry( let countryOff = CountryDouble.createCountry(
@@ -39,10 +38,9 @@ struct FlatBuffersDoubleTests {
97, 121, 0, 0, 97, 121, 0, 0,
] ]
// swiftformat:enable all // swiftformat:enable all
#expect(b.sizedByteArray == v) XCTAssertEqual(b.sizedByteArray, v)
} }
@Test
func testCreateFinishWithPrefix() { func testCreateFinishWithPrefix() {
var b = FlatBufferBuilder(initialSize: 16) var b = FlatBufferBuilder(initialSize: 16)
let countryOff = CountryDouble.createCountry( let countryOff = CountryDouble.createCountry(
@@ -59,7 +57,7 @@ struct FlatBuffersDoubleTests {
0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0, 0, 6, 0, 0, 0, 78, 111, 114, 119, 97, 121, 0, 0,
] ]
// swiftformat:enable all // swiftformat:enable all
#expect(b.sizedByteArray == v) XCTAssertEqual(b.sizedByteArray, v)
} }
} }
@@ -15,11 +15,11 @@
*/ */
import Foundation import Foundation
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
struct FlatBuffersMoreDefaults { class FlatBuffersMoreDefaults: XCTestCase {
func testFlatbuffersObject() { func testFlatbuffersObject() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
@@ -27,58 +27,61 @@ struct FlatBuffersMoreDefaults {
fbb.finish(offset: root) fbb.finish(offset: root)
var byteBuffer = fbb.sizedBuffer var byteBuffer = fbb.sizedBuffer
let defaults: MoreDefaults = getRoot(byteBuffer: &byteBuffer) let defaults: MoreDefaults = getRoot(byteBuffer: &byteBuffer)
#expect(defaults.emptyString == "") XCTAssertEqual(defaults.emptyString, "")
#expect(defaults.someString == "some") XCTAssertEqual(defaults.someString, "some")
#expect(defaults.ints.isEmpty == true) XCTAssertEqual(defaults.ints.isEmpty, true)
#expect(defaults.floats.isEmpty == true) XCTAssertEqual(defaults.floats.isEmpty, true)
#expect(defaults.bools.isEmpty == true) XCTAssertEqual(defaults.bools.isEmpty, true)
#expect(defaults.ints.count == 0) XCTAssertEqual(defaults.ints.count, 0)
#expect(defaults.floats.count == 0) XCTAssertEqual(defaults.floats.count, 0)
#expect(defaults.abcs.count == 0) XCTAssertEqual(defaults.abcs.count, 0)
#expect(defaults.bools.count == 0) XCTAssertEqual(defaults.bools.count, 0)
} }
func testFlatbuffersObjectAPI() { func testFlatbuffersObjectAPI() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
let defaults = MoreDefaultsT() let defaults = MoreDefaultsT()
#expect(defaults.emptyString == "") XCTAssertEqual(defaults.emptyString, "")
#expect(defaults.someString == "some") XCTAssertEqual(defaults.someString, "some")
#expect(defaults.ints == []) XCTAssertEqual(defaults.ints, [])
#expect(defaults.floats == []) XCTAssertEqual(defaults.floats, [])
#expect(defaults.abcs == []) XCTAssertEqual(defaults.abcs, [])
#expect(defaults.bools == []) XCTAssertEqual(defaults.bools, [])
var buffer = defaults.serialize(builder: &fbb, type: MoreDefaults.self) var buffer = defaults.serialize(builder: &fbb, type: MoreDefaults.self)
let fDefaults: MoreDefaults = getRoot(byteBuffer: &buffer) let fDefaults: MoreDefaults = getRoot(byteBuffer: &buffer)
#expect(fDefaults.emptyString == "") XCTAssertEqual(fDefaults.emptyString, "")
#expect(fDefaults.someString == "some") XCTAssertEqual(fDefaults.someString, "some")
#expect(fDefaults.ints.isEmpty == true) XCTAssertEqual(fDefaults.ints.isEmpty, true)
#expect(fDefaults.floats.isEmpty == true) XCTAssertEqual(fDefaults.floats.isEmpty, true)
#expect(fDefaults.ints.count == 0) XCTAssertEqual(fDefaults.ints.count, 0)
#expect(fDefaults.floats.count == 0) XCTAssertEqual(fDefaults.floats.count, 0)
#expect(fDefaults.abcs.count == 0) XCTAssertEqual(fDefaults.abcs.count, 0)
#expect(fDefaults.bools.count == 0) XCTAssertEqual(fDefaults.bools.count, 0)
} }
@Test func testEncoding() {
func testEncoding() throws {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
let root = MoreDefaults.createMoreDefaults(&fbb) let root = MoreDefaults.createMoreDefaults(&fbb)
fbb.finish(offset: root) fbb.finish(offset: root)
var sizedBuffer = fbb.sizedBuffer var sizedBuffer = fbb.sizedBuffer
struct Test: Decodable { do {
var emptyString: String struct Test: Decodable {
var someString: String var emptyString: String
var someString: String
}
let reader: MoreDefaults = try getCheckedRoot(byteBuffer: &sizedBuffer)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
XCTAssertEqual(value.someString, "some")
XCTAssertEqual(value.emptyString, "")
} catch {
XCTFail(error.localizedDescription)
} }
let reader: MoreDefaults = try getCheckedRoot(byteBuffer: &sizedBuffer)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
#expect(value.someString == "some")
#expect(value.emptyString == "")
} }
} }
@@ -14,20 +14,25 @@
* limitations under the License. * limitations under the License.
*/ */
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
final class FlatbuffersVerifierTests { final class FlatbuffersVerifierTests: XCTestCase {
private var buffer: ByteBuffer var buffer: ByteBuffer!
private var validFlatbuffersObject: ByteBuffer var validFlatbuffersObject: ByteBuffer!
private var invalidFlatbuffersObject: ByteBuffer var invalidFlatbuffersObject: ByteBuffer!
private var invalidFlatbuffersObject2: ByteBuffer var invalidFlatbuffersObject2: ByteBuffer!
private var invalidFlatbuffersObject3: ByteBuffer var invalidFlatbuffersObject3: ByteBuffer!
init() { override func setUp() {
// swiftformat:disable all // swiftformat:disable all
let memory = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 1)
buffer = ByteBuffer(assumingMemoryBound: memory, capacity: 32)
add(buffer: &buffer, v: 4, p: 16)
add(buffer: &buffer, v: 4, p: 20)
validFlatbuffersObject = ByteBuffer(bytes: [ validFlatbuffersObject = ByteBuffer(bytes: [
48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0,
0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0,
@@ -89,250 +94,186 @@ final class FlatbuffersVerifierTests {
109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100,
0x00, 111, 0, 0, 0, 0x00, 111, 0, 0, 0,
]) ])
let memory = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 1)
buffer = ByteBuffer(assumingMemoryBound: memory, capacity: 32)
add(buffer: &buffer, v: 4, p: 16)
add(buffer: &buffer, v: 4, p: 20)
// swiftformat:enable all // swiftformat:enable all
} }
@Test func testVeriferInitPassing() {
func testVeriferInitPassing() throws {
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1) let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
var buffer = ByteBuffer( var buffer = ByteBuffer(
assumingMemoryBound: memory, assumingMemoryBound: memory,
capacity: Int(FlatBufferMaxSize) - 1) capacity: Int(FlatBufferMaxSize) - 1)
_ = try Verifier(buffer: &buffer) XCTAssertNoThrow(try Verifier(buffer: &buffer))
} }
@Test
func testVeriferInitFailing() { func testVeriferInitFailing() {
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1) let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
var buffer = ByteBuffer( var buffer = ByteBuffer(
assumingMemoryBound: memory, assumingMemoryBound: memory,
capacity: Int(FlatBufferMaxSize) + 1) capacity: Int(FlatBufferMaxSize) + 1)
#expect(throws: FlatbuffersErrors.exceedsMaxSizeAllowed) { XCTAssertThrowsError(try Verifier(buffer: &buffer))
try Verifier(buffer: &buffer)
}
} }
@Test
func testFailingID() { func testFailingID() {
let dutData: [UInt8] = [1, 2, 3, 4, 5, 6, 7] let dutData: [UInt8] = [1, 2, 3, 4, 5, 6, 7]
var buff = ByteBuffer(bytes: dutData) var buff = ByteBuffer(bytes: dutData)
#expect(throws: FlatbuffersErrors.bufferDoesntContainID) { do {
let _: Monster = try getCheckedRoot(byteBuffer: &buff, fileId: "ABCD") let _: Monster = try getCheckedRoot(byteBuffer: &buff, fileId: "ABCD")
XCTFail("This should always fail")
} catch {
XCTAssertEqual(error as? FlatbuffersErrors, .bufferDoesntContainID)
} }
} }
@Test func testVerifierCheckAlignment() {
func testVerifierCheckAlignment() throws {
let verifier = try! Verifier(buffer: &buffer) let verifier = try! Verifier(buffer: &buffer)
#expect(throws: FlatbuffersErrors.missAlignedPointer( do {
position: 20,
type: "Int"))
{
try verifier.isAligned(position: 20, type: Int.self) try verifier.isAligned(position: 20, type: Int.self)
} catch {
XCTAssertEqual(
error as? FlatbuffersErrors,
.missAlignedPointer(position: 20, type: "Int"))
} }
XCTAssertNoThrow(try verifier.isAligned(position: 16, type: Int.self))
try verifier.isAligned(position: 16, type: Int.self)
let newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false) let newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
try newVerifer.isAligned(position: 16, type: Int.self) XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self))
} }
@Test func testRangeInBuffer() {
func testRangeInBuffer() throws {
var verifier = try! Verifier(buffer: &buffer) var verifier = try! Verifier(buffer: &buffer)
let size = MemoryLayout<Int64>.size let size = MemoryLayout<Int64>.size
try verifier.rangeInBuffer(position: 24, size: size) XCTAssertNoThrow(try verifier.rangeInBuffer(position: 24, size: size))
#expect(throws: FlatbuffersErrors.outOfBounds(position: 34, end: 32)) { XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
try verifier.rangeInBuffer(position: 26, size: size) XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
} XCTAssertThrowsError(try verifier.rangeInBuffer(position: 30, size: size))
#expect(throws: FlatbuffersErrors.outOfBounds(position: 34, end: 32)) { XCTAssertThrowsError(try verifier.rangeInBuffer(position: 32, size: size))
try verifier.rangeInBuffer( XCTAssertThrowsError(try verifier.rangeInBuffer(position: 34, size: size))
position: 26,
size: size)
}
#expect(throws: FlatbuffersErrors.outOfBounds(position: 38, end: 32)) {
try verifier.rangeInBuffer(
position: 30,
size: size)
}
#expect(throws: FlatbuffersErrors.outOfBounds(position: 40, end: 32)) {
try verifier.rangeInBuffer(
position: 32,
size: size)
}
#expect(throws: FlatbuffersErrors.outOfBounds(position: 42, end: 32)) {
try verifier.rangeInBuffer(
position: 34,
size: size)
}
verifier = try! Verifier( verifier = try! Verifier(
buffer: &buffer, buffer: &buffer,
options: .init(maxDepth: 0, maxTableCount: 0, maxApparentSize: 4)) options: .init(maxDepth: 0, maxTableCount: 0, maxApparentSize: 4))
do {
#expect(throws: FlatbuffersErrors.apparentSizeTooLarge) {
try verifier.rangeInBuffer(position: 24, size: size) try verifier.rangeInBuffer(position: 24, size: size)
} catch {
XCTAssertEqual(
error as! FlatbuffersErrors,
.apparentSizeTooLarge)
} }
} }
@Test func testPositionInBuffer() {
func testPositionInBuffer() throws {
let verifier = try! Verifier(buffer: &buffer) let verifier = try! Verifier(buffer: &buffer)
try verifier.inBuffer(position: 0, of: Int64.self) XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self))
try verifier.inBuffer(position: 24, of: Int64.self) XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self))
XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
#expect( XCTAssertThrowsError(try verifier.inBuffer(position: 25, of: Int64.self))
throws: FlatbuffersErrors.missAlignedPointer( XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int32.self))
position: -9, XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int64.self))
type: "Int64")) XCTAssertThrowsError(try verifier.inBuffer(position: 30, of: Int64.self))
{ XCTAssertThrowsError(try verifier.inBuffer(position: 32, of: Int64.self))
try verifier.inBuffer(position: -9, of: Int64.self) XCTAssertThrowsError(try verifier.inBuffer(position: 34, of: Int64.self))
}
#expect(
throws: FlatbuffersErrors.missAlignedPointer(
position: 25,
type: "Int64"))
{
try verifier.inBuffer(position: 25, of: Int64.self)
}
#expect(
throws: FlatbuffersErrors.missAlignedPointer(
position: 26,
type: "Int32"))
{
try verifier.inBuffer(position: 26, of: Int32.self)
}
#expect(
throws: FlatbuffersErrors.missAlignedPointer(
position: 26,
type: "Int64"))
{
try verifier.inBuffer(position: 26, of: Int64.self)
}
#expect(
throws: FlatbuffersErrors.missAlignedPointer(
position: 30,
type: "Int64"))
{
try verifier.inBuffer(position: 30, of: Int64.self)
}
#expect(throws: FlatbuffersErrors.outOfBounds(position: 40, end: 32)) {
try verifier.inBuffer(
position: 32,
of: Int64.self)
}
#expect(
throws: FlatbuffersErrors.missAlignedPointer(
position: 34,
type: "Int64"))
{
try verifier.inBuffer(position: 34, of: Int64.self)
}
} }
@Test func testVisitTable() {
func testVisitTable() throws {
var verifier = try! Verifier(buffer: &validFlatbuffersObject) var verifier = try! Verifier(buffer: &validFlatbuffersObject)
_ = try verifier.visitTable(at: 48) XCTAssertNoThrow(try verifier.visitTable(at: 48))
verifier.reset() verifier.reset()
} }
@Test func testTableVerifier() {
func testTableVerifier() throws {
var verifier = try! Verifier(buffer: &validFlatbuffersObject) var verifier = try! Verifier(buffer: &validFlatbuffersObject)
var tableVerifer = try! verifier.visitTable(at: 48) var tableVerifer = try! verifier.visitTable(at: 48)
#expect(verifier.depth == 1) XCTAssertEqual(verifier.depth, 1)
#expect(verifier.tableCount == 1) XCTAssertEqual(verifier.tableCount, 1)
try tableVerifer.visit( XCTAssertNoThrow(
field: 4, try tableVerifer.visit(
fieldName: "Vec", field: 4,
required: false, fieldName: "Vec",
type: Vec3.self) required: false,
type: Vec3.self))
XCTAssertNoThrow(
try tableVerifer.visit(
field: 8,
fieldName: "hp",
required: false,
type: Int16.self))
try tableVerifer.visit( XCTAssertNoThrow(
field: 8, try tableVerifer.visit(
fieldName: "hp", field: 10,
required: false, fieldName: "name",
type: Int16.self) required: true,
type: ForwardOffset<String>.self))
try tableVerifer.visit( XCTAssertNoThrow(
field: 10, try tableVerifer.visit(
fieldName: "name", field: 14,
required: true, fieldName: "inventory",
type: ForwardOffset<String>.self) required: false,
type: ForwardOffset<Vector<UInt8, UInt8>>.self))
try tableVerifer.visit( XCTAssertNoThrow(
field: 14, try tableVerifer.visit(
fieldName: "inventory", field: 22,
required: false, fieldName: "test4",
type: ForwardOffset<Vector<UInt8, UInt8>>.self) required: false,
type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>
.self))
try tableVerifer.visit( XCTAssertNoThrow(
field: 22, try tableVerifer.visit(
fieldName: "test4", field: 24,
required: false, fieldName: "Vector of strings",
type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>> required: false,
.self) type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self))
try tableVerifer.visit( do {
field: 24,
fieldName: "Vector of strings",
required: false,
type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self)
#expect(throws: FlatbuffersErrors.missAlignedPointer(
position: 25,
type: "UInt16"))
{
try tableVerifer.visit( try tableVerifer.visit(
field: 13, field: 13,
fieldName: "notvalid", fieldName: "notvalid",
required: false, required: false,
type: Int16.self) type: Int16.self)
} catch {
XCTAssertEqual(
error as! FlatbuffersErrors,
.missAlignedPointer(position: 25, type: "UInt16"))
} }
try tableVerifer.visit( do {
unionKey: 18, try tableVerifer.visit(
unionField: 20, unionKey: 18,
unionKeyName: "testType", unionField: 20,
fieldName: "test", unionKeyName: "testType",
required: false, fieldName: "test",
completion: { (verifier, key: MyGame_Example_Any_, pos) in required: false,
switch key { completion: { (verifier, key: MyGame_Example_Any_, pos) in
case .none_: switch key {
break // NOTE - SWIFT doesnt support none case .none_:
case .monster: break
try ForwardOffset<MyGame_Example_Monster>.verify( case .monster:
&verifier, try ForwardOffset<MyGame_Example_Monster>.verify(
at: pos, &verifier,
of: MyGame_Example_Monster.self) at: pos,
case .testsimpletablewithenum: of: MyGame_Example_Monster.self)
try ForwardOffset<MyGame_Example_TestSimpleTableWithEnum>.verify(
&verifier,
at: pos,
of: MyGame_Example_TestSimpleTableWithEnum.self)
case .mygameExample2Monster:
try ForwardOffset<MyGame_Example2_Monster>.verify(
&verifier,
at: pos,
of: MyGame_Example2_Monster.self)
}
})
case .testsimpletablewithenum:
break
case .mygameExample2Monster:
break
}
})
} catch {
XCTAssertEqual(
error as! FlatbuffersErrors,
.missAlignedPointer(position: 25, type: "UInt16"))
}
tableVerifer.finish() tableVerifer.finish()
#expect(verifier.depth == 0) XCTAssertEqual(verifier.depth, 0)
} }
@Test func testVerifyUnionVectors() {
func testVerifyUnionVectors() throws {
// swiftformat:disable all // swiftformat:disable all
var byteBuffer = ByteBuffer(bytes: [ var byteBuffer = ByteBuffer(bytes: [
20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0,
@@ -340,11 +281,10 @@ final class FlatbuffersVerifierTests {
0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0,
]) ])
// swiftformat:enable all // swiftformat:enable all
_ = try getCheckedRoot(byteBuffer: &byteBuffer) as Movie XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie)
} }
@Test func testErrorWrongFileId() {
func testErrorWrongFileId() throws{
// swiftformat:disable all // swiftformat:disable all
var byteBuffer = ByteBuffer(bytes: [ var byteBuffer = ByteBuffer(bytes: [
20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0,
@@ -352,14 +292,12 @@ final class FlatbuffersVerifierTests {
0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0,
]) ])
// swiftformat:enable all // swiftformat:enable all
#expect(throws: FlatbuffersErrors.bufferIdDidntMatchPassedId) { XCTAssertThrowsError(
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &byteBuffer, byteBuffer: &byteBuffer,
fileId: "FLEX") as Movie fileId: "FLEX") as Movie)
}
} }
@Test
func testVerifyPrefixedBuffer() { func testVerifyPrefixedBuffer() {
// swiftformat:disable all // swiftformat:disable all
var byteBuffer = ByteBuffer(bytes: [ var byteBuffer = ByteBuffer(bytes: [
@@ -368,71 +306,41 @@ final class FlatbuffersVerifierTests {
0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0,
]) ])
// swiftformat:enable all // swiftformat:enable all
#expect(throws: FlatbuffersErrors.prefixedSizeNotEqualToBufferSize) { XCTAssertThrowsError(
try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie)
}
} }
@Test func testFullVerifier() {
func testFullVerifier() throws { XCTAssertNoThrow(
_ =
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster)
} }
@Test func testFullVerifierWithFileId() {
func testFullVerifierWithFileId() throws { XCTAssertNoThrow(
_ = try getCheckedRoot( try getCheckedRoot(
byteBuffer: &validFlatbuffersObject, byteBuffer: &validFlatbuffersObject,
fileId: MyGame_Example_Monster.id) as MyGame_Example_Monster fileId: MyGame_Example_Monster.id) as MyGame_Example_Monster)
} }
@Test
func testInvalidBuffer() { func testInvalidBuffer() {
#expect(throws: FlatbuffersErrors.self) { XCTAssertThrowsError(
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &self.invalidFlatbuffersObject) as MyGame_Example_Monster byteBuffer: &invalidFlatbuffersObject) as MyGame_Example_Monster)
}
} }
@Test
func testInvalidBuffer2() { func testInvalidBuffer2() {
#expect(throws: FlatbuffersErrors.self) { XCTAssertThrowsError(
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &self.invalidFlatbuffersObject2) as MyGame_Example_Monster byteBuffer: &invalidFlatbuffersObject2) as MyGame_Example_Monster)
}
} }
@Test
func testInvalidBuffer3() { func testInvalidBuffer3() {
#expect(throws: FlatbuffersErrors.self) { XCTAssertThrowsError(
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &self.invalidFlatbuffersObject3) as MyGame_Example_Monster byteBuffer: &invalidFlatbuffersObject3) as MyGame_Example_Monster)
}
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/9082"))
func testRejectsTruncatedScalarVector() {
// swiftformat:disable all
var byteBuffer = ByteBuffer(bytes: [
16, 0, 0, 0,
6, 0, 8, 0,
4, 0, 0, 0,
0, 0, 0, 0,
12, 0, 0, 0,
8, 0, 0, 0,
0, 0, 0, 0,
2, 0, 0, 0,
65, 66,
])
// swiftformat:enable all
#expect(throws: FlatbuffersErrors.self) {
try getCheckedRoot(byteBuffer: &byteBuffer) as Swift_Tests_Vectors
}
}
@Test
func testValidUnionBuffer() { func testValidUnionBuffer() {
let string = "Awesome \\\\t\t\nstring!" let string = "Awesome \\\\t\t\nstring!"
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -454,14 +362,9 @@ final class FlatbuffersVerifierTests {
charactersVectorOffset: characterVector) charactersVectorOffset: characterVector)
Movie.finish(&fb, end: end) Movie.finish(&fb, end: end)
var buf = fb.sizedBuffer var buf = fb.sizedBuffer
do { XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie)
_ = try getCheckedRoot(byteBuffer: &buf) as Movie
} catch {
Issue.record(error)
}
} }
@Test
func testNestedTables() throws { func testNestedTables() throws {
var builder = FlatBufferBuilder() var builder = FlatBufferBuilder()
let name = builder.create(string: "Monster") let name = builder.create(string: "Monster")
@@ -480,22 +383,22 @@ final class FlatbuffersVerifierTests {
var verifier = try! Verifier(buffer: &sizedBuffer) var verifier = try! Verifier(buffer: &sizedBuffer)
var tableVerifer = try! verifier.visitTable( var tableVerifer = try! verifier.visitTable(
at: try getOffset(at: 0, within: verifier)) at: try getOffset(at: 0, within: verifier))
#expect(verifier.depth == 1) XCTAssertEqual(verifier.depth, 1)
#expect(verifier.tableCount == 1) XCTAssertEqual(verifier.tableCount, 1)
let position = try tableVerifer.dereference(28)! let position = try tableVerifer.dereference(28)!
var nestedTable = try verifier.visitTable( var nestedTable = try verifier.visitTable(
at: try getOffset(at: position, within: verifier)) at: try getOffset(at: position, within: verifier))
#expect(verifier.depth == 2) XCTAssertEqual(verifier.depth, 2)
#expect(verifier.tableCount == 2) XCTAssertEqual(verifier.tableCount, 2)
nestedTable.finish() nestedTable.finish()
#expect(verifier.depth == 1) XCTAssertEqual(verifier.depth, 1)
#expect(verifier.tableCount == 2) XCTAssertEqual(verifier.tableCount, 2)
tableVerifer.finish() tableVerifer.finish()
#expect(verifier.depth == 0) XCTAssertEqual(verifier.depth, 0)
#expect(verifier.tableCount == 2) XCTAssertEqual(verifier.tableCount, 2)
} }
func add(buffer: inout ByteBuffer, v: Int32, p: Int) { func add(buffer: inout ByteBuffer, v: Int32, p: Int) {
@@ -74,7 +74,7 @@ public struct Property_Mutable: FlatBufferStruct, FlatbuffersVectorInitializable
} }
} }
public struct TestMutatingBool: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct TestMutatingBool: 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 }
@@ -398,7 +398,7 @@ public struct MyGame_Example_LargeArrayStruct_Mutable: FlatBufferStruct, Flatbuf
} }
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
public struct MyGame_Example_ArrayTable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_ArrayTable: 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 }
@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct DataModel_A: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct DataModel_A: 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 }
@@ -5,568 +5,206 @@
// swiftlint:disable all // swiftlint:disable all
// swiftformat:disable all // swiftformat:disable all
#if !os(Windows) && compiler(>=6.0) #if !os(Windows)
import FlatBuffers
import Foundation import Foundation
import GRPCCore import GRPC
import GRPCNIOTransportCore import NIO
import NIOHTTP1
import FlatBuffers
public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage {}
/// Usage: instantiate MyGame.Example.MonsterStorageServiceClient, then call methods of this protocol to make API calls. public extension GRPCFlatBufPayload {
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) init(serializedByteBuffer: inout NIO.ByteBuffer) throws {
extension FlatBuffersMessageSerializer: MessageSerializer { self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: serializedByteBuffer.readableBytesView, count: serializedByteBuffer.readableBytes))
public func serialize<Bytes>(_ message: Message) throws -> Bytes where Bytes : GRPCCore.GRPCContiguousBytes { }
do { func serialize(into buffer: inout NIO.ByteBuffer) throws {
return try self.serialize(message: message) { GRPCNIOTransportBytes($0) } as! Bytes withUnsafeReadableBytes { buffer.writeBytes($0) }
} catch let error {
throw RPCError(
code: .invalidArgument,
message: "Can't serialize message",
cause: error
)
}
} }
} }
extension Message: GRPCFlatBufPayload {}
/// Usage: instantiate MyGame_Example_MonsterStorageServiceClient, then call methods of this protocol to make API calls.
public protocol MyGame_Example_MonsterStorageClientProtocol: GRPCClient {
var serviceName: String { get }
var interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol? { get }
func Store(
_ request: Message<MyGame_Example_Monster>
, callOptions: CallOptions?
) -> UnaryCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>
func Retrieve(
_ request: Message<MyGame_Example_Stat>
, callOptions: CallOptions?,
handler: @escaping (Message<MyGame_Example_Monster>) -> Void
) -> ServerStreamingCall<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>
func GetMaxHitPoint(
callOptions: CallOptions?
) -> ClientStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>
func GetMinMaxHitPoints(
callOptions: CallOptions?,
handler: @escaping (Message<MyGame_Example_Stat> ) -> Void
) -> BidirectionalStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>
@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, *) extension MyGame_Example_MonsterStorageClientProtocol {
public enum MyGame_Example_MonsterStorage: Sendable {
public static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage")
public enum Method: Sendable {
public enum Store: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = MyGame_Example_Stat
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage"),
method: "Store"
)
}
public enum Retrieve: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = MyGame_Example_Monster
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage"),
method: "Retrieve"
)
}
public enum GetMaxHitPoint: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = MyGame_Example_Stat
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage"),
method: "GetMaxHitPoint"
)
}
public enum GetMinMaxHitPoints: Sendable {
public typealias Input = FlatBufferBuilder
public typealias Output = MyGame_Example_Stat
public static let descriptor = GRPCCore.MethodDescriptor(
service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage"),
method: "GetMinMaxHitPoints"
)
}
public static let descriptors: [GRPCCore.MethodDescriptor] = [
Store.descriptor,
Retrieve.descriptor,
GetMaxHitPoint.descriptor,
GetMinMaxHitPoints.descriptor,
]
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public var serviceName: String { "MyGame.Example.MonsterStorage" }
extension GRPCCore.ServiceDescriptor {
public static let MyGame_Example_MonsterStorage = GRPCCore.ServiceDescriptor(fullyQualifiedService: "MyGame.Example.MonsterStorage")
}
// MARK: MyGame.Example.MonsterStorage Server
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension MyGame_Example_MonsterStorage {
public protocol StreamingServiceProtocol: GRPCCore.RegistrableRPCService {
func Store(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>
func Retrieve(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Monster>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>>
func GetMaxHitPoint(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>
func GetMinMaxHitPoints(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>
}
public protocol ServiceProtocol: MyGame_Example_MonsterStorage.StreamingServiceProtocol {
func Store(
request: GRPCCore.ServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>>
func Retrieve(
request: GRPCCore.ServerRequest<GRPCMessage<MyGame_Example_Monster>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>>
func GetMaxHitPoint(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>>
func GetMinMaxHitPoints(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>
}
public protocol SimpleServiceProtocol: MyGame_Example_MonsterStorage.ServiceProtocol {
func Store(
request: GRPCMessage<MyGame_Example_Stat>,
context: GRPCCore.ServerContext
) async throws -> GRPCMessage<MyGame_Example_Stat>
func Retrieve(
request: GRPCMessage<MyGame_Example_Monster>,
response: GRPCCore.RPCWriter<GRPCMessage<MyGame_Example_Monster>>,
context: GRPCCore.ServerContext
) async throws
func GetMaxHitPoint(
request: GRPCCore.RPCAsyncSequence<GRPCMessage<MyGame_Example_Stat>, any Swift.Error>,
context: GRPCCore.ServerContext
) async throws -> GRPCMessage<MyGame_Example_Stat>
func GetMinMaxHitPoints(
request: GRPCCore.RPCAsyncSequence<GRPCMessage<MyGame_Example_Stat>, any Swift.Error>,
response: GRPCCore.RPCWriter<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension MyGame_Example_MonsterStorage.StreamingServiceProtocol {
public func registerMethods<Transport>(with router: inout GRPCCore.RPCRouter<Transport>) where Transport: GRPCCore.ServerTransport {
router.registerHandler(
forMethod: MyGame_Example_MonsterStorage.Method.Store.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
handler: { request, context in
try await self.Store(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: MyGame_Example_MonsterStorage.Method.Retrieve.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Monster>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Monster>>(),
handler: { request, context in
try await self.Retrieve(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: MyGame_Example_MonsterStorage.Method.GetMaxHitPoint.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
handler: { request, context in
try await self.GetMaxHitPoint(
request: request,
context: context
)
}
)
router.registerHandler(
forMethod: MyGame_Example_MonsterStorage.Method.GetMinMaxHitPoints.descriptor,
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
handler: { request, context in
try await self.GetMinMaxHitPoints(
request: request,
context: context
)
}
)
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension MyGame_Example_MonsterStorage.ServiceProtocol {
public func Store( public func Store(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>, _ request: Message<MyGame_Example_Monster>
context: GRPCCore.ServerContext , callOptions: CallOptions? = nil
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>> { ) -> UnaryCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
let response = try await self.Store( return self.makeUnaryCall(
request: GRPCCore.ServerRequest(stream: request), path: "/MyGame.Example.MonsterStorage/Store",
context: context
)
return GRPCCore.StreamingServerResponse(single: response)
}
public func Retrieve(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Monster>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>> {
let response = try await self.Retrieve(
request: GRPCCore.ServerRequest(stream: request),
context: context
)
return response
}
public func GetMaxHitPoint(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>> {
let response = try await self.GetMaxHitPoint(
request: request, request: request,
context: context callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeStoreInterceptors() ?? []
) )
return GRPCCore.StreamingServerResponse(single: response)
} }
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension MyGame_Example_MonsterStorage.SimpleServiceProtocol {
public func Store(
request: GRPCCore.ServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>> {
return GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>>(
message: try await self.Store(
request: request.message,
context: context
),
metadata: [:]
)
}
public func Retrieve( public func Retrieve(
request: GRPCCore.ServerRequest<GRPCMessage<MyGame_Example_Monster>>, _ request: Message<MyGame_Example_Stat>
context: GRPCCore.ServerContext , callOptions: CallOptions? = nil,
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>> { handler: @escaping (Message<MyGame_Example_Monster>) -> Void
return GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>>( ) -> ServerStreamingCall<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>> {
metadata: [:], return self.makeServerStreamingCall(
producer: { writer in path: "/MyGame.Example.MonsterStorage/Retrieve",
try await self.Retrieve( request: request,
request: request.message, callOptions: callOptions ?? self.defaultCallOptions,
response: writer, interceptors: self.interceptors?.makeRetrieveInterceptors() ?? [],
context: context handler: handler
)
return [:]
}
) )
} }
public func GetMaxHitPoint( public func GetMaxHitPoint(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>, callOptions: CallOptions? = nil
context: GRPCCore.ServerContext ) -> ClientStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
) async throws -> GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>> { return self.makeClientStreamingCall(
return GRPCCore.ServerResponse<GRPCMessage<MyGame_Example_Stat>>( path: "/MyGame.Example.MonsterStorage/GetMaxHitPoint",
message: try await self.GetMaxHitPoint( callOptions: callOptions ?? self.defaultCallOptions,
request: request.messages, interceptors: self.interceptors?.makeGetMaxHitPointInterceptors() ?? []
context: context
),
metadata: [:]
) )
} }
public func GetMinMaxHitPoints( public func GetMinMaxHitPoints(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>, callOptions: CallOptions? = nil,
context: GRPCCore.ServerContext handler: @escaping (Message<MyGame_Example_Stat> ) -> Void
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>> { ) -> BidirectionalStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
return GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>( return self.makeBidirectionalStreamingCall(
metadata: [:], path: "/MyGame.Example.MonsterStorage/GetMinMaxHitPoints",
producer: { writer in callOptions: callOptions ?? self.defaultCallOptions,
try await self.GetMinMaxHitPoints( interceptors: self.interceptors?.makeGetMinMaxHitPointsInterceptors() ?? [],
request: request.messages, handler: handler
response: writer,
context: context
)
return [:]
}
) )
} }
} }
public protocol MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when invoking 'Store'.
func makeStoreInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
// MARK: MyGame.Example.MonsterStorage Client /// - Returns: Interceptors to use when invoking 'Retrieve'.
func makeRetrieveInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>]
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) /// - Returns: Interceptors to use when invoking 'GetMaxHitPoint'.
extension MyGame_Example_MonsterStorage { func makeGetMaxHitPointInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
public protocol ClientProtocol: Sendable {
func Store<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Stat>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result
) async throws -> Result where Result: Sendable
func Retrieve<Result>( /// - Returns: Interceptors to use when invoking 'GetMinMaxHitPoints'.
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Monster>>, func makeGetMinMaxHitPointsInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Monster>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Monster>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Monster>>) async throws -> Result
) async throws -> Result where Result: Sendable
func GetMaxHitPoint<Result>( }
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result
) async throws -> Result where Result: Sendable
func GetMinMaxHitPoints<Result>( public final class MyGame_Example_MonsterStorageServiceClient: MyGame_Example_MonsterStorageClientProtocol {
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>, public let channel: GRPCChannel
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>, public var defaultCallOptions: CallOptions
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>, public var interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol?
options: GRPCCore.CallOptions,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result
) async throws -> Result where Result: Sendable
public init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
} }
} }
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public protocol MyGame_Example_MonsterStorageProvider: CallHandlerProvider {
extension MyGame_Example_MonsterStorage { var interceptors: MyGame_Example_MonsterStorageServerInterceptorFactoryProtocol? { get }
public struct Client<Transport>: ClientProtocol where Transport: GRPCCore.ClientTransport { func Store(request: Message<MyGame_Example_Monster>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<MyGame_Example_Stat>>
private let client: GRPCCore.GRPCClient<Transport> func Retrieve(request: Message<MyGame_Example_Stat>, context: StreamingResponseCallContext<Message<MyGame_Example_Monster>>) -> EventLoopFuture<GRPCStatus>
func GetMaxHitPoint(context: UnaryResponseCallContext<Message<MyGame_Example_Stat>>) -> EventLoopFuture<(StreamEvent<Message<MyGame_Example_Monster>>) -> Void>
public init(wrapping client: GRPCCore.GRPCClient<Transport>) { func GetMinMaxHitPoints(context: StreamingResponseCallContext<Message<MyGame_Example_Stat>>) -> EventLoopFuture<(StreamEvent<Message<MyGame_Example_Monster>>) -> Void>
self.client = client
}
public func Store<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Stat>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.client.unary(
request: request,
descriptor: MyGame_Example_MonsterStorage.Method.Store.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func Retrieve<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Monster>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Monster>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Monster>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Monster>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.client.serverStreaming(
request: request,
descriptor: MyGame_Example_MonsterStorage.Method.Retrieve.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func GetMaxHitPoint<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.client.clientStreaming(
request: request,
descriptor: MyGame_Example_MonsterStorage.Method.GetMaxHitPoint.descriptor,
serializer: serializer,
deserializer: deserializer,
options: options,
onResponse: handleResponse
)
}
public func GetMinMaxHitPoints<Result>(
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>,
serializer: some GRPCCore.MessageSerializer<GRPCMessage<MyGame_Example_Stat>>,
deserializer: some GRPCCore.MessageDeserializer<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.client.bidirectionalStreaming(
request: request,
descriptor: MyGame_Example_MonsterStorage.Method.GetMinMaxHitPoints.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, *) public extension MyGame_Example_MonsterStorageProvider {
extension MyGame_Example_MonsterStorage.ClientProtocol {
public func Store<Result>(
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Stat>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { response in try response.message }
) async throws -> Result where Result: Sendable {
try await self.Store(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
options: options,
onResponse: handleResponse
)
}
public func Retrieve<Result>( var serviceName: Substring { return "MyGame.Example.MonsterStorage" }
request: GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Monster>>,
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Monster>>) async throws -> Result
) async throws -> Result where Result: Sendable {
try await self.Retrieve(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Monster>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Monster>>(),
options: options,
onResponse: handleResponse
)
}
public func GetMaxHitPoint<Result>( func handle(method name: Substring, context: CallHandlerContext) -> GRPCServerHandlerProtocol? {
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>, switch name {
options: GRPCCore.CallOptions = .defaults, case "Store":
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { response in try response.message } return UnaryServerHandler(
) async throws -> Result where Result: Sendable { context: context,
try await self.GetMaxHitPoint( requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Monster>>(),
request: request, responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Stat>>(),
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(), interceptors: self.interceptors?.makeStoreInterceptors() ?? [],
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(), userFunction: self.Store(request:context:))
options: options,
onResponse: handleResponse
)
}
public func GetMinMaxHitPoints<Result>( case "Retrieve":
request: GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>, return ServerStreamingServerHandler(
options: GRPCCore.CallOptions = .defaults, context: context,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Stat>>(),
) async throws -> Result where Result: Sendable { responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Monster>>(),
try await self.GetMinMaxHitPoints( interceptors: self.interceptors?.makeRetrieveInterceptors() ?? [],
request: request, userFunction: self.Retrieve(request:context:))
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(), case "GetMaxHitPoint":
options: options, return ClientStreamingServerHandler(
onResponse: handleResponse context: context,
) requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Monster>>(),
responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Stat>>(),
interceptors: self.interceptors?.makeGetMaxHitPointInterceptors() ?? [],
observerFactory: self.GetMaxHitPoint(context:))
case "GetMinMaxHitPoints":
return BidirectionalStreamingServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Monster>>(),
responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Stat>>(),
interceptors: self.interceptors?.makeGetMinMaxHitPointsInterceptors() ?? [],
observerFactory: self.GetMinMaxHitPoints(context:))
default: return nil;
}
} }
} }
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public protocol MyGame_Example_MonsterStorageServerInterceptorFactoryProtocol {
extension MyGame_Example_MonsterStorage.ClientProtocol { /// - Returns: Interceptors to use when handling 'Store'.
public func Store<Result>( /// Defaults to calling `self.makeInterceptors()`.
_ message: GRPCMessage<MyGame_Example_Stat>, func makeStoreInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
metadata: GRPCCore.Metadata = [:],
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { try $0.message }
) async throws -> Result where Result: Sendable {
let request = GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Stat>>(
message: message,
metadata: metadata
)
return try await self.Store(
request: request,
options: options,
onResponse: handleResponse
)
}
public func Retrieve<Result>( /// - Returns: Interceptors to use when handling 'Retrieve'.
_ message: GRPCMessage<MyGame_Example_Monster>, /// Defaults to calling `self.makeInterceptors()`.
metadata: GRPCCore.Metadata = [:], func makeRetrieveInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>]
options: GRPCCore.CallOptions = .defaults,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Monster>>) async throws -> Result
) async throws -> Result where Result: Sendable {
let request = GRPCCore.ClientRequest<GRPCMessage<MyGame_Example_Monster>>(
message: message,
metadata: metadata
)
return try await self.Retrieve(
request: request,
options: options,
onResponse: handleResponse
)
}
public func GetMaxHitPoint<Result>( /// - Returns: Interceptors to use when handling 'GetMaxHitPoint'.
metadata: GRPCCore.Metadata = [:], /// Defaults to calling `self.makeInterceptors()`.
options: GRPCCore.CallOptions = .defaults, func makeGetMaxHitPointInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<GRPCMessage<MyGame_Example_Stat>>) async throws -> Void,
onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result = { try $0.message }
) async throws -> Result where Result: Sendable {
let request = GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>(
metadata: metadata,
producer: producer
)
return try await self.GetMaxHitPoint(
request: request,
options: options,
onResponse: handleResponse
)
}
public func GetMinMaxHitPoints<Result>( /// - Returns: Interceptors to use when handling 'GetMinMaxHitPoints'.
metadata: GRPCCore.Metadata = [:], /// Defaults to calling `self.makeInterceptors()`.
options: GRPCCore.CallOptions = .defaults, func makeGetMinMaxHitPointsInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter<GRPCMessage<MyGame_Example_Stat>>) async throws -> Void,
onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse<GRPCMessage<MyGame_Example_Stat>>) async throws -> Result
) async throws -> Result where Result: Sendable {
let request = GRPCCore.StreamingClientRequest<GRPCMessage<MyGame_Example_Stat>>(
metadata: metadata,
producer: producer
)
return try await self.GetMinMaxHitPoints(
request: request,
options: options,
onResponse: handleResponse
)
}
} }
#endif #endif
@@ -662,7 +662,7 @@ public struct MyGame_Example_StructOfStructsOfStructs_Mutable: FlatBufferStruct,
} }
} }
public struct MyGame_InParentNamespace: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_InParentNamespace: 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 }
@@ -712,7 +712,7 @@ public class MyGame_InParentNamespaceT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_InParentNamespace.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_InParentNamespace.self) }
} }
public struct MyGame_Example2_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example2_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 }
@@ -762,7 +762,7 @@ public class MyGame_Example2_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example2_Monster.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example2_Monster.self) }
} }
internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
internal var __buffer: ByteBuffer! { return _accessor.bb } internal var __buffer: ByteBuffer! { return _accessor.bb }
@@ -840,7 +840,7 @@ internal class MyGame_Example_TestSimpleTableWithEnumT: NativeObject {
internal func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_TestSimpleTableWithEnum.self) } internal func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_TestSimpleTableWithEnum.self) }
} }
public struct MyGame_Example_Stat: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_Stat: 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 }
@@ -976,7 +976,7 @@ public class MyGame_Example_StatT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Stat.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Stat.self) }
} }
public struct MyGame_Example_Referrable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_Referrable: 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 }
@@ -1079,7 +1079,7 @@ public class MyGame_Example_ReferrableT: NativeObject {
} }
/// an example documentation comment: "monster object" /// an example documentation comment: "monster object"
public struct MyGame_Example_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_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 }
@@ -2213,7 +2213,7 @@ public class MyGame_Example_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Monster.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Monster.self) }
} }
public struct MyGame_Example_TypeAliases: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_TypeAliases: 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 }
@@ -31,7 +31,7 @@ extension ABC: Encodable {
} }
} }
public struct MoreDefaults: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MoreDefaults: 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 }
@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct Swift_Tests_NanInfTable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable { public struct Swift_Tests_NanInfTable: 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 }
@@ -31,7 +31,7 @@ extension optional_scalars_OptionalByte: Encodable {
} }
} }
public struct optional_scalars_ScalarStuff: FlatBufferVerifiableTable, FlatbuffersVectorInitializable { public struct optional_scalars_ScalarStuff: 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 }
@@ -320,7 +320,7 @@ public struct FallingTub_Mutable: FlatBufferStruct, FlatbuffersVectorInitializab
} }
} }
public struct Attacker: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct Attacker: 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 }
@@ -398,7 +398,7 @@ public class AttackerT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: Attacker.self) } public func serialize() -> ByteBuffer { return serialize(type: Attacker.self) }
} }
public struct HandFan: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct HandFan: 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 }
@@ -476,7 +476,7 @@ public class HandFanT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: HandFan.self) } public func serialize() -> ByteBuffer { return serialize(type: HandFan.self) }
} }
public struct Movie: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct Movie: 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 }
@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct Swift_Tests_Vectors: FlatBufferVerifiableTable, FlatbuffersVectorInitializable { public struct Swift_Tests_Vectors: 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 }
@@ -16,19 +16,17 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Foundation import XCTest
import Testing
struct FlexBuffersJSONTests { final class FlexBuffersJSONTests: XCTestCase {
@Test
func testEncodingJSON() throws { func testEncodingJSON() throws {
let buf: ByteBuffer = createProperBuffer().sizedByteBuffer let buf: ByteBuffer = createProperBuffer().sizedByteBuffer
let reference = try getRoot(buffer: buf)! let reference = try getRoot(buffer: buf)!
let json = reference.jsonString() let json = reference.jsonString()
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
json == json,
"{\"bar\": [1, 2, 3], \"bar3\": [1, 2, 3], \"bool\": true, \"bools\": [true, false, true, false], \"foo\": 100.0, \"mymap\": {\"foo\": \"Fred\"}, \"vec\": [-100, \"Fred\", 4.0, \"M\", false, 4.0]}" "{\"bar\": [1, 2, 3], \"bar3\": [1, 2, 3], \"bool\": true, \"bools\": [true, false, true, false], \"foo\": 100.0, \"mymap\": {\"foo\": \"Fred\"}, \"vec\": [-100, \"Fred\", 4.0, \"M\", false, 4.0]}"
) )
// swiftformat:enable all // swiftformat:enable all
@@ -39,15 +37,15 @@ struct FlexBuffersJSONTests {
with: data, with: data,
options: []) as! [String: Any] options: []) as! [String: Any]
#expect(decodedData["bar"] as! [Int] == [1, 2, 3]) XCTAssertEqual(decodedData["bar"] as! [Int], [1, 2, 3])
#expect(decodedData["bar3"] as! [Int] == [1, 2, 3]) XCTAssertEqual(decodedData["bar3"] as! [Int], [1, 2, 3])
let vec: [Any] = decodedData["vec"] as! [Any] let vec: [Any] = decodedData["vec"] as! [Any]
#expect(vec[0] as! Int == -100) XCTAssertEqual(vec[0] as! Int, -100)
#expect(vec[1] as! String == "Fred") XCTAssertEqual(vec[1] as! String, "Fred")
#expect(vec[2] as! Double == 4.0) XCTAssertEqual(vec[2] as! Double, 4.0)
#expect(vec[3] as! String == "M") XCTAssertEqual(vec[3] as! String, "M")
#expect(vec[4] as! Bool == false) XCTAssertEqual(vec[4] as! Bool, false)
#expect(vec[5] as! Double == 4.0) XCTAssertEqual(vec[5] as! Double, 4.0)
} }
} }
@@ -15,26 +15,22 @@
*/ */
import Common import Common
import Foundation import XCTest
import Testing
@testable import FlexBuffers @testable import FlexBuffers
struct FlexBuffersReaderTests { final class FlexBuffersReaderTests: XCTestCase {
@Test
func testReadingProperBuffer() throws { func testReadingProperBuffer() throws {
let buf: ByteBuffer = createProperBuffer().byteBuffer let buf: ByteBuffer = createProperBuffer().byteBuffer
try validate(buffer: buf) try validate(buffer: buf)
} }
@Test
func testReadingSizedBuffer() throws { func testReadingSizedBuffer() throws {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
try validate(buffer: buf) try validate(buffer: buf)
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/8642"))
func testReset() throws { func testReset() throws {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -42,87 +38,87 @@ struct FlexBuffersReaderTests {
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(data: fbx.data)) try validate(buffer: ByteBuffer(data: fbx.data))
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
fbx.reset() fbx.reset()
#expect(fbx.writerIndex == 0) XCTAssertEqual(fbx.writerIndex, 0)
#expect(fbx.capacity == 8) XCTAssertEqual(fbx.capacity, 8)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(data: fbx.data)) try validate(buffer: ByteBuffer(data: fbx.data))
fbx.reset(keepingCapacity: true) fbx.reset(keepingCapacity: true)
#expect(fbx.writerIndex == 0) XCTAssertEqual(fbx.writerIndex, 0)
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(data: fbx.data)) try validate(buffer: ByteBuffer(data: fbx.data))
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
} }
private func validate(buffer buf: ByteBuffer) throws { private func validate(buffer buf: ByteBuffer) throws {
let reference = try getRoot(buffer: buf)! let reference = try getRoot(buffer: buf)!
#expect(reference.type == .map) XCTAssertEqual(reference.type, .map)
let map = reference.map! let map = reference.map!
#expect(map.count == 7) XCTAssertEqual(map.count, 7)
let vecRef = map["vec"]! let vecRef = map["vec"]!
#expect(vecRef.type == .vector) XCTAssertEqual(vecRef.type, .vector)
let vec = vecRef.vector! let vec = vecRef.vector!
#expect(vec.count == 6) XCTAssertEqual(vec.count, 6)
#expect(vec[0]?.type == .int) XCTAssertEqual(vec[0]?.type, .int)
#expect(vec[0]?.int == -100) XCTAssertEqual(vec[0]?.int, -100)
#expect(vec[1]?.type == .string) XCTAssertEqual(vec[1]?.type, .string)
#expect(vec[1]?.cString == "Fred") XCTAssertEqual(vec[1]?.cString, "Fred")
#expect(vec[1]?.int == nil) XCTAssertNil(vec[1]?.int)
#expect(vec[2]?.double == 4.0) XCTAssertEqual(vec[2]?.double, 4.0)
#expect(vec[3]?.type == .blob) XCTAssertTrue(vec[3]?.type == .blob)
let blob = vec[3]!.blob { pointer in let blob = vec[3]!.blob { pointer in
Array(pointer) Array(pointer)
} }
#expect(blob?.count == 1) XCTAssertEqual(blob?.count, 1)
#expect(blob?[0] == 77) XCTAssertEqual(blob?[0], 77)
#expect(vec[4]?.type == .bool) XCTAssertEqual(vec[4]?.type, .bool)
#expect(vec[4]?.bool == false) XCTAssertEqual(vec[4]?.bool, false)
#expect(vec[5]?.double == 4.0) // Shared with vec[2] XCTAssertEqual(vec[5]?.double, 4.0) // Shared with vec[2]
let barVec = map["bar"]!.typedVector! let barVec = map["bar"]!.typedVector!
#expect(barVec.count == 3) XCTAssertEqual(barVec.count, 3)
#expect(barVec[2]?.int == 3) XCTAssertEqual(barVec[2]?.int, 3)
#expect(barVec[2]?.asInt() == UInt8(3)) XCTAssertEqual(barVec[2]?.asInt(), UInt8(3))
let fixedVec = map["bar3"]!.fixedTypedVector! let fixedVec = map["bar3"]!.fixedTypedVector!
#expect(fixedVec.count == 3) XCTAssertEqual(fixedVec.count, 3)
#expect(fixedVec[2]?.int == 3) XCTAssertEqual(fixedVec[2]?.int, 3)
#expect(fixedVec[2]?.asInt() == UInt8(3)) XCTAssertEqual(fixedVec[2]?.asInt(), UInt8(3))
#expect(map["bool"]?.bool == true) XCTAssertEqual(map["bool"]?.bool, true)
let boolsVector = map["bools"]!.typedVector! let boolsVector = map["bools"]!.typedVector!
#expect(boolsVector.type == .bool) XCTAssertEqual(boolsVector.type, .bool)
#expect(boolsVector[0]?.bool == true) XCTAssertEqual(boolsVector[0]?.bool, true)
#expect(boolsVector[1]?.bool == false) XCTAssertEqual(boolsVector[1]?.bool, false)
let bools = [true, false, true, false] let bools = [true, false, true, false]
boolsVector.withUnsafeRawBufferPointer { buff in boolsVector.withUnsafeRawBufferPointer { buff in
for i in 0..<boolsVector.count { for i in 0..<boolsVector.count {
#expect(buff.load(fromByteOffset: i, as: Bool.self) == bools[i]) XCTAssertEqual(buff.load(fromByteOffset: i, as: Bool.self), bools[i])
} }
} }
#expect(map["foo"]?.double == 100) XCTAssertEqual(map["foo"]?.double, 100)
#expect(map["unknown"] == nil) XCTAssertNil(map["unknown"])
let mymap = map["mymap"]?.map let mymap = map["mymap"]?.map
// Check if both addresses used are the same for keys and strings // Check if both addresses used are the same for keys and strings
#expect(mymap?.keys[0]?.cString == map.keys[4]?.cString) XCTAssertEqual(mymap?.keys[0]?.cString, map.keys[4]?.cString)
map.keys[4]?.withUnsafeRawPointer { pointer in map.keys[4]?.withUnsafeRawPointer { pointer in
mymap?.keys[0]?.withUnsafeRawPointer { mymapPointer in mymap?.keys[0]?.withUnsafeRawPointer { mymapPointer in
#expect(pointer == mymapPointer) XCTAssertEqual(pointer, mymapPointer)
} }
} }
#expect(mymap?.values[0]?.cString == vec[1]?.cString) XCTAssertEqual(mymap?.values[0]?.cString, vec[1]?.cString)
vec[1]?.withUnsafeRawPointer { pointer in vec[1]?.withUnsafeRawPointer { pointer in
mymap?.values[0]?.withUnsafeRawPointer { mymapPointer in mymap?.values[0]?.withUnsafeRawPointer { mymapPointer in
#expect(pointer == mymapPointer) XCTAssertEqual(pointer, mymapPointer)
} }
} }
} }
@@ -131,7 +127,7 @@ struct FlexBuffersReaderTests {
#if os(macOS) #if os(macOS)
// Gets the current path of this test file then // Gets the current path of this test file then
// strips out the nested directories. // strips out the nested directories.
let filePath = URL(filePath: #filePath) let filePath = URL(filePath: #file)
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
@@ -140,4 +136,5 @@ struct FlexBuffersReaderTests {
return FileManager.default.currentDirectoryPath return FileManager.default.currentDirectoryPath
#endif #endif
} }
} }
@@ -16,12 +16,10 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Foundation import XCTest
import Testing
struct FlexBuffersStringTests { final class FlexBuffersStringTests: XCTestCase {
@Test
func testEncodingUnicodeString() { func testEncodingUnicodeString() {
let text = "プ画をみて✋" let text = "プ画をみて✋"
@@ -40,6 +38,6 @@ struct FlexBuffersStringTests {
return String(data: data, encoding: .unicode) return String(data: data, encoding: .unicode)
} }
#expect(builtString == text) XCTAssertEqual(builtString, text)
} }
} }
@@ -16,10 +16,9 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Testing import XCTest
struct FlexBuffersWriterTests { final class FlexBuffersWriterTests: XCTestCase {
@Test
func testDeallocation() { func testDeallocation() {
let buf: ByteBuffer = { let buf: ByteBuffer = {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
@@ -29,13 +28,12 @@ struct FlexBuffersWriterTests {
}() }()
buf.withUnsafeBytes { buf.withUnsafeBytes {
#expect( XCTAssertEqual(
Array($0) == Array($0),
[5, 72, 101, 108, 108, 111, 0, 6, 20, 1]) [5, 72, 101, 108, 108, 111, 0, 6, 20, 1])
} }
} }
@Test
func testAddingVectorOfScalars() { func testAddingVectorOfScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -47,8 +45,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
10, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 10, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0,
0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 20, 0, 0, 0, 1, 41, 46, 2, 40, 1, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 20, 0, 0, 0, 1, 41, 46, 2, 40, 1,
@@ -57,7 +55,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testAddingVectorOfUnsignedScalars() { func testAddingVectorOfUnsignedScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -69,8 +66,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
10, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
@@ -81,7 +78,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testAddingVectorOfBools() { func testAddingVectorOfBools() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -93,14 +89,13 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[4, 1, 0, 1, 0, 1, 5, 144, 2, 40, 1]) [4, 1, 0, 1, 0, 1, 5, 144, 2, 40, 1])
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testSortingWithinMap() { func testSortingWithinMap() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.map { fbx.map {
@@ -111,8 +106,8 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
98, 111, 111, 108, 50, 0, 98, 111, 111, 108, 49, 0, 2, 7, 14, 2, 1, 2, 1, 0, 104, 104, 4, 98, 111, 111, 108, 50, 0, 98, 111, 111, 108, 49, 0, 2, 7, 14, 2, 1, 2, 1, 0, 104, 104, 4,
36, 1, 36, 1,
@@ -122,7 +117,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testSharingKeyWithinMap() { func testSharingKeyWithinMap() {
var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings) var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings)
fbx.map { fbx.map {
@@ -134,8 +128,8 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
119, 101, 108, 99, 111, 109, 101, 0, 7, 119, 101, 108, 99, 111, 109, 101, 0, 3, 18, 19, 119, 101, 108, 99, 111, 109, 101, 0, 7, 119, 101, 108, 99, 111, 109, 101, 0, 3, 18, 19,
20, 3, 1, 3, 15, 16, 17, 20, 20, 20, 6, 36, 1, 20, 3, 1, 3, 15, 16, 17, 20, 20, 20, 6, 36, 1,
@@ -145,21 +139,19 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testNestingVectorInMap() { func testNestingVectorInMap() {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
flexbufferGolden flexbufferGolden
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testAddingNil() { func testAddingNil() {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -173,15 +165,14 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[118, 0, 1, 3, 1, 1, 1, 0, 0, 2, 36, 1] [118, 0, 1, 3, 1, 1, 1, 0, 0, 2, 36, 1]
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testAddingManually() { func testAddingManually() {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -218,15 +209,14 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
flexbufferGolden flexbufferGolden
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testEncodingAllTypes() { func testEncodingAllTypes() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -250,8 +240,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
allTypesGolden) allTypesGolden)
// swiftformat:enable all // swiftformat:enable all
} }
@@ -15,7 +15,7 @@
*/ */
import Foundation import Foundation
import Testing import XCTest
@testable import FlatBuffers @testable import FlatBuffers
@@ -24,9 +24,8 @@ typealias Monster = MyGame_Example_Monster
typealias Vec3 = MyGame_Example_Vec3 typealias Vec3 = MyGame_Example_Vec3
typealias Stat = MyGame_Example_Stat typealias Stat = MyGame_Example_Stat
struct FlatBuffersMonsterWriterTests { class FlatBuffersMonsterWriterTests: XCTestCase {
@Test
func testData() { func testData() {
// swiftformat:disable all // swiftformat:disable all
let data: [UInt8] = [ let data: [UInt8] = [
@@ -48,12 +47,11 @@ struct FlatBuffersMonsterWriterTests {
readVerifiedMonster(fb: _data) readVerifiedMonster(fb: _data)
} }
@Test
func testCreateMonster() { func testCreateMonster() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -77,12 +75,11 @@ struct FlatBuffersMonsterWriterTests {
readMonster(monster: monster) readMonster(monster: monster)
} }
@Test
func testCreateMonsterResizedBuffer() { func testCreateMonsterResizedBuffer() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -101,12 +98,11 @@ struct FlatBuffersMonsterWriterTests {
readVerifiedMonster(fb: bytes.sizedBuffer) readVerifiedMonster(fb: bytes.sizedBuffer)
} }
@Test
func testCreateMonsterPrefixed() { func testCreateMonsterPrefixed() {
let bytes = createMonster(withPrefix: true) let bytes = createMonster(withPrefix: true)
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
bytes.sizedByteArray == bytes.sizedByteArray,
[ [
44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 44, 1, 0, 0, 44, 0, 0, 0, 77, 79, 78, 83, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28,
0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0,
@@ -127,7 +123,6 @@ struct FlatBuffersMonsterWriterTests {
readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer)) readMonster(monster: getPrefixedSizeRoot(byteBuffer: &buffer))
} }
@Test
func testCreateMonsterUsingCreateMonsterMethodWithNilPos() { func testCreateMonsterUsingCreateMonsterMethodWithNilPos() {
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Frodo") let name = fbb.create(string: "Frodo")
@@ -137,11 +132,10 @@ struct FlatBuffersMonsterWriterTests {
fbb.finish(offset: root) fbb.finish(offset: root)
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
#expect(newMonster.pos == nil) XCTAssertNil(newMonster.pos)
#expect(newMonster.name == "Frodo") XCTAssertEqual(newMonster.name, "Frodo")
} }
@Test
func testCreateMonsterUsingCreateMonsterMethodWithPosX() { func testCreateMonsterUsingCreateMonsterMethodWithPosX() {
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
let name = fbb.create(string: "Barney") let name = fbb.create(string: "Barney")
@@ -161,11 +155,10 @@ struct FlatBuffersMonsterWriterTests {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
#expect(newMonster.pos!.x == 10) XCTAssertEqual(newMonster.pos!.x, 10)
#expect(newMonster.name == "Barney") XCTAssertEqual(newMonster.name, "Barney")
} }
@Test
func testReadMonsterFromUnsafePointerWithoutCopying() { func testReadMonsterFromUnsafePointerWithoutCopying() {
// swiftformat:disable all // swiftformat:disable all
var array: [UInt8] = [ var array: [UInt8] = [
@@ -197,7 +190,6 @@ struct FlatBuffersMonsterWriterTests {
readObjectApi(monster: unpacked) readObjectApi(monster: unpacked)
} }
@Test
func testArrayOfBools() { func testArrayOfBools() {
let boolArray = [false, true, false, true, false, true, false] let boolArray = [false, true, false, true, false, true, false]
var fbb = FlatBufferBuilder(initialSize: 1) var fbb = FlatBufferBuilder(initialSize: 1)
@@ -213,41 +205,37 @@ struct FlatBuffersMonsterWriterTests {
let monster: Monster = getRoot(byteBuffer: &buffer) let monster: Monster = getRoot(byteBuffer: &buffer)
let values = monster.testarrayofbools let values = monster.testarrayofbools
#expect(boolArray.count == values.count) XCTAssertEqual(boolArray.count, values.count)
for (index, bool) in monster.testarrayofbools.enumerated() { for (index, bool) in monster.testarrayofbools.enumerated() {
#expect(bool == boolArray[index]) XCTAssertEqual(bool, boolArray[index])
} }
} }
func readVerifiedMonster(fb: ByteBuffer) { func readVerifiedMonster(fb: ByteBuffer) {
var byteBuffer = fb var byteBuffer = fb
do { XCTAssertNoThrow(
try readMonster( try readMonster(
monster: getCheckedRoot( monster: getCheckedRoot(
byteBuffer: &byteBuffer) as MyGame_Example_Monster) byteBuffer: &byteBuffer) as MyGame_Example_Monster))
} catch {
Issue.record(error)
}
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/8133"))
func testUnalignedRead() { func testUnalignedRead() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
let testAligned: () -> Bool = { let testAligned: () -> Bool = {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
var monster: Monster = getRoot(byteBuffer: &buffer) var monster: Monster = getRoot(byteBuffer: &buffer)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
#expect(testAligned() == true) XCTAssertEqual(testAligned(), true)
let testUnaligned: () -> Bool = { let testUnaligned: () -> Bool = {
var bytes: [UInt8] = [0x00] var bytes: [UInt8] = [0x00]
bytes.append(contentsOf: fbb.sizedByteArray) bytes.append(contentsOf: fbb.sizedByteArray)
return bytes.withUnsafeMutableBytes { ptr in return bytes.withUnsafeMutableBytes { ptr in
guard var baseAddress = ptr.baseAddress else { guard var baseAddress = ptr.baseAddress else {
Issue.record("Base pointer is not defined") XCTFail("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -256,14 +244,13 @@ struct FlatBuffersMonsterWriterTests {
assumingMemoryBound: unlignedPtr, assumingMemoryBound: unlignedPtr,
capacity: ptr.count - 1) capacity: ptr.count - 1)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
#expect(testUnaligned() == true) XCTAssertEqual(testUnaligned(), true)
} }
@Test
func testReadingRemovedSizeUnalignedBuffer() { func testReadingRemovedSizeUnalignedBuffer() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: true) let fbb = createMonster(withPrefix: true)
@@ -272,7 +259,7 @@ struct FlatBuffersMonsterWriterTests {
bytes.append(contentsOf: fbb.sizedByteArray) bytes.append(contentsOf: fbb.sizedByteArray)
return bytes.withUnsafeMutableBytes { ptr in return bytes.withUnsafeMutableBytes { ptr in
guard var baseAddress = ptr.baseAddress else { guard var baseAddress = ptr.baseAddress else {
Issue.record("Base pointer is not defined") XCTFail("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -282,14 +269,13 @@ struct FlatBuffersMonsterWriterTests {
capacity: ptr.count - 1) capacity: ptr.count - 1)
var newBuf = FlatBuffersUtils.removeSizePrefix(bb: bytes) var newBuf = FlatBuffersUtils.removeSizePrefix(bb: bytes)
var monster: Monster = getRoot(byteBuffer: &newBuf) var monster: Monster = getRoot(byteBuffer: &newBuf)
readFlatbufferMonster(monster: &monster) self.readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
#expect(testUnaligned() == true) XCTAssertEqual(testUnaligned(), true)
} }
@Test
func testForceRetainedObject() { func testForceRetainedObject() {
let byteBuffer = { let byteBuffer = {
// swiftformat:disable all // swiftformat:disable all
@@ -395,95 +381,95 @@ struct FlatBuffersMonsterWriterTests {
var fb = fb var fb = fb
let monster: Monster = getRoot(byteBuffer: &fb) let monster: Monster = getRoot(byteBuffer: &fb)
#expect(monster.mutate(mana: 10) == false) XCTAssertFalse(monster.mutate(mana: 10))
#expect(monster.testarrayoftables[0].name == "Barney") XCTAssertEqual(monster.testarrayoftables[0].name, "Barney")
#expect(monster.testarrayoftables[1].name == "Frodo") XCTAssertEqual(monster.testarrayoftables[1].name, "Frodo")
#expect(monster.testarrayoftables[2].name == "Wilma") XCTAssertEqual(monster.testarrayoftables[2].name, "Wilma")
// Example of searching for a table by the key // Example of searching for a table by the key
#expect(monster.testarrayoftablesBy(key: "Frodo") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Frodo"))
#expect(monster.testarrayoftablesBy(key: "Barney") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Barney"))
#expect(monster.testarrayoftablesBy(key: "Wilma") != nil) XCTAssertNotNil(monster.testarrayoftablesBy(key: "Wilma"))
#expect(monster.testType == .monster) XCTAssertEqual(monster.testType, .monster)
#expect(monster.mutate(inventory: 1, at: 0) == true) XCTAssertEqual(monster.mutate(inventory: 1, at: 0), true)
#expect(monster.mutate(inventory: 2, at: 1) == true) XCTAssertEqual(monster.mutate(inventory: 2, at: 1), true)
#expect(monster.mutate(inventory: 3, at: 2) == true) XCTAssertEqual(monster.mutate(inventory: 3, at: 2), true)
#expect(monster.mutate(inventory: 4, at: 3) == true) XCTAssertEqual(monster.mutate(inventory: 4, at: 3), true)
#expect(monster.mutate(inventory: 5, at: 4) == true) XCTAssertEqual(monster.mutate(inventory: 5, at: 4), true)
for i in 0..<monster.inventory.count { for i in 0..<monster.inventory.count {
#expect(monster.inventory[i] == Byte(i + 1)) XCTAssertEqual(monster.inventory[i], Byte(i + 1))
} }
#expect(monster.mutate(inventory: 0, at: 0) == true) XCTAssertEqual(monster.mutate(inventory: 0, at: 0), true)
#expect(monster.mutate(inventory: 1, at: 1) == true) XCTAssertEqual(monster.mutate(inventory: 1, at: 1), true)
#expect(monster.mutate(inventory: 2, at: 2) == true) XCTAssertEqual(monster.mutate(inventory: 2, at: 2), true)
#expect(monster.mutate(inventory: 3, at: 3) == true) XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true)
#expect(monster.mutate(inventory: 4, at: 4) == true) XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true)
let vec = monster.mutablePos let vec = monster.mutablePos
#expect(vec?.x == 1) XCTAssertEqual(vec?.x, 1)
#expect(vec?.mutate(x: 55.0) == true) XCTAssertTrue(vec?.mutate(x: 55.0) ?? false)
#expect(vec?.mutate(test1: 55) == true) XCTAssertTrue(vec?.mutate(test1: 55) ?? false)
#expect(vec?.x == 55.0) XCTAssertEqual(vec?.x, 55.0)
#expect(vec?.test1 == 55.0) XCTAssertEqual(vec?.test1, 55.0)
#expect(vec?.mutate(x: 1) == true) XCTAssertTrue(vec?.mutate(x: 1) ?? false)
#expect(vec?.x == 1) XCTAssertEqual(vec?.x, 1)
#expect(vec?.mutate(test1: 3) == true) XCTAssertTrue(vec?.mutate(test1: 3) ?? false)
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
let orignalValues = mutableTest4[0].a let orignalValues = mutableTest4[0].a
#expect(mutableTest4[0].mutate(a: 100) == true) XCTAssertEqual(mutableTest4[0].mutate(a: 100), true)
#expect(monster.test4[0].a != orignalValues) XCTAssertNotEqual(monster.test4[0].a, orignalValues)
#expect(monster.test4[0].a == 100) XCTAssertEqual(monster.test4[0].a, 100)
#expect(mutableTest4[0].mutate(a: orignalValues) == true) XCTAssertEqual(mutableTest4[0].mutate(a: orignalValues), true)
} }
func readFlatbufferMonster(monster: inout MyGame_Example_Monster) { func readFlatbufferMonster(monster: inout MyGame_Example_Monster) {
#expect(monster.hp == 80) XCTAssertEqual(monster.hp, 80)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.name == "MyMonster") XCTAssertEqual(monster.name, "MyMonster")
let pos = monster.pos let pos = monster.pos
#expect(pos?.x == 1) XCTAssertEqual(pos?.x, 1)
#expect(pos?.y == 2) XCTAssertEqual(pos?.y, 2)
#expect(pos?.z == 3) XCTAssertEqual(pos?.z, 3)
#expect(pos?.test1 == 3) XCTAssertEqual(pos?.test1, 3)
#expect(pos?.test2 == .green) XCTAssertEqual(pos?.test2, .green)
let test = pos?.test3 let test = pos?.test3
#expect(test?.a == 5) XCTAssertEqual(test?.a, 5)
#expect(test?.b == 6) XCTAssertEqual(test?.b, 6)
#expect(monster.testType == .monster) XCTAssertEqual(monster.testType, .monster)
let monster2 = monster.test(type: Monster.self) let monster2 = monster.test(type: Monster.self)
#expect(monster2?.name == "Fred") XCTAssertEqual(monster2?.name, "Fred")
#expect(monster.mutate(mana: 10) == false) XCTAssertEqual(monster.mutate(mana: 10), false)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.inventory.count == 5) XCTAssertEqual(monster.inventory.count, 5)
var sum: Byte = 0 var sum: Byte = 0
for inventory in monster.inventory { for inventory in monster.inventory {
sum += inventory sum += inventory
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
monster.withUnsafePointerToInventory { ptr, count in monster.withUnsafePointerToInventory { ptr, count in
var sum: UInt8 = 0 var sum: UInt8 = 0
for pointee in ptr.startIndex..<ptr.endIndex { for pointee in ptr.startIndex..<ptr.endIndex {
sum += ptr[pointee] sum += ptr[pointee]
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
} }
#expect(monster.test4.count == 2) XCTAssertEqual(monster.test4.count, 2)
let test4 = monster.test4 let test4 = monster.test4
var sum0 = 0 var sum0 = 0
for test0 in test4 { for test0 in test4 {
sum0 += Int(test0.a) + Int(test0.b) sum0 += Int(test0.a) + Int(test0.b)
} }
#expect(sum0 == 100) XCTAssertEqual(sum0, 100)
monster.withUnsafePointerToTest4 { ptr, count in monster.withUnsafePointerToTest4 { ptr, count in
guard let ptr = ptr.baseAddress else { return } guard let ptr = ptr.baseAddress else { return }
@@ -499,7 +485,7 @@ struct FlatBuffersMonsterWriterTests {
pointerSum += Int(bindedMemory[pointee].a) + pointerSum += Int(bindedMemory[pointee].a) +
Int(bindedMemory[pointee].b) Int(bindedMemory[pointee].b)
} }
#expect(pointerSum == 100) XCTAssertEqual(pointerSum, 100)
} }
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
@@ -507,84 +493,87 @@ struct FlatBuffersMonsterWriterTests {
for test0 in mutableTest4 { for test0 in mutableTest4 {
sum2 += Int(test0.a) + Int(test0.b) sum2 += Int(test0.a) + Int(test0.b)
} }
#expect(sum2 == 100) XCTAssertEqual(sum2, 100)
let stringArray = monster.testarrayofstring let stringArray = monster.testarrayofstring
#expect(stringArray.count == 2) XCTAssertEqual(stringArray.count, 2)
#expect(stringArray[0] == "test1") XCTAssertEqual(stringArray[0], "test1")
#expect(stringArray[1] == "test2") XCTAssertEqual(stringArray[1], "test2")
#expect(monster.testbool == true) XCTAssertEqual(monster.testbool, true)
let array = monster.nameSegmentArray let array = monster.nameSegmentArray
#expect(String(bytes: array ?? [], encoding: .utf8) == "MyMonster") XCTAssertEqual(String(bytes: array ?? [], encoding: .utf8), "MyMonster")
if 0 == monster.testarrayofbools.count { if 0 == monster.testarrayofbools.count {
#expect(monster.testarrayofbools.isEmpty == true) XCTAssertEqual(monster.testarrayofbools.isEmpty, true)
} else { } else {
#expect(monster.testarrayofbools.isEmpty == false) XCTAssertEqual(monster.testarrayofbools.isEmpty, false)
} }
} }
func readObjectApi(monster: MyGame_Example_MonsterT) { func readObjectApi(monster: MyGame_Example_MonsterT) {
#expect(monster.hp == 80) XCTAssertEqual(monster.hp, 80)
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.name == "MyMonster") XCTAssertEqual(monster.name, "MyMonster")
let pos = monster.pos let pos = monster.pos
#expect(pos?.x == 1) XCTAssertEqual(pos?.x, 1)
#expect(pos?.y == 2) XCTAssertEqual(pos?.y, 2)
#expect(pos?.z == 3) XCTAssertEqual(pos?.z, 3)
#expect(pos?.test1 == 3) XCTAssertEqual(pos?.test1, 3)
#expect(pos?.test2 == .green) XCTAssertEqual(pos?.test2, .green)
let test = pos?.test3 let test = pos?.test3
#expect(test?.a == 5) XCTAssertEqual(test?.a, 5)
#expect(test?.b == 6) XCTAssertEqual(test?.b, 6)
let monster2 = monster.test?.value as? MyGame_Example_MonsterT let monster2 = monster.test?.value as? MyGame_Example_MonsterT
#expect(monster2?.name == "Fred") XCTAssertEqual(monster2?.name, "Fred")
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
monster.mana = 10 monster.mana = 10
#expect(monster.mana == 10) XCTAssertEqual(monster.mana, 10)
monster.mana = 150 monster.mana = 150
#expect(monster.mana == 150) XCTAssertEqual(monster.mana, 150)
#expect(monster.inventory.count == 5) XCTAssertEqual(monster.inventory.count, 5)
var sum: Byte = 0 var sum: Byte = 0
for i in monster.inventory { for i in monster.inventory {
sum += i sum += i
} }
#expect(sum == 10) XCTAssertEqual(sum, 10)
#expect(monster.test4.count == 2) XCTAssertEqual(monster.test4.count, 2)
var sum0 = 0 var sum0 = 0
for test in monster.test4 { for test in monster.test4 {
sum0 += Int(test.a) + Int(test.b) sum0 += Int(test.a) + Int(test.b)
} }
#expect(sum0 == 100) XCTAssertEqual(sum0, 100)
#expect(monster.testbool == true) XCTAssertEqual(monster.testbool, true)
} }
@Test func testEncoding() {
func testEncoding() throws {
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
var sizedBuffer = fbb.sizedBuffer var sizedBuffer = fbb.sizedBuffer
struct Test: Decodable { do {
struct Pos: Decodable { struct Test: Decodable {
let x, y, z: Int struct Pos: Decodable {
let x, y, z: Int
}
let hp: Int
let inventory: [UInt8]
let name: String
let pos: Pos
} }
let hp: Int let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer)
let inventory: [UInt8] let encoder = JSONEncoder()
let name: String encoder.keyEncodingStrategy = .convertToSnakeCase
let pos: Pos let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
XCTAssertEqual(value.name, "MyMonster")
XCTAssertEqual(value.pos.x, 1)
XCTAssertEqual(value.pos.y, 2)
XCTAssertEqual(value.pos.z, 3)
} catch {
XCTFail(error.localizedDescription)
} }
let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(reader)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let value = try decoder.decode(Test.self, from: data)
#expect(value.name == "MyMonster")
#expect(value.pos.x == 1)
#expect(value.pos.y == 2)
#expect(value.pos.z == 3)
} }
var jsonData: String { var jsonData: String {
@@ -662,7 +662,7 @@ public struct MyGame_Example_StructOfStructsOfStructs_Mutable: FlatBufferStruct,
} }
} }
public struct MyGame_InParentNamespace: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_InParentNamespace: 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 }
@@ -712,7 +712,7 @@ public class MyGame_InParentNamespaceT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_InParentNamespace.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_InParentNamespace.self) }
} }
public struct MyGame_Example2_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example2_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 }
@@ -762,7 +762,7 @@ public class MyGame_Example2_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example2_Monster.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example2_Monster.self) }
} }
internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
internal var __buffer: ByteBuffer! { return _accessor.bb } internal var __buffer: ByteBuffer! { return _accessor.bb }
@@ -840,7 +840,7 @@ internal class MyGame_Example_TestSimpleTableWithEnumT: NativeObject {
internal func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_TestSimpleTableWithEnum.self) } internal func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_TestSimpleTableWithEnum.self) }
} }
public struct MyGame_Example_Stat: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_Stat: 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 }
@@ -976,7 +976,7 @@ public class MyGame_Example_StatT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Stat.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Stat.self) }
} }
public struct MyGame_Example_Referrable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_Referrable: 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 }
@@ -1079,7 +1079,7 @@ public class MyGame_Example_ReferrableT: NativeObject {
} }
/// an example documentation comment: "monster object" /// an example documentation comment: "monster object"
public struct MyGame_Example_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_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 }
@@ -2213,7 +2213,7 @@ public class MyGame_Example_MonsterT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Monster.self) } public func serialize() -> ByteBuffer { return serialize(type: MyGame_Example_Monster.self) }
} }
public struct MyGame_Example_TypeAliases: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct MyGame_Example_TypeAliases: 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 }
@@ -16,19 +16,17 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Foundation import XCTest
import Testing
struct FlexBuffersJSONTests { final class FlexBuffersJSONTests: XCTestCase {
@Test
func testEncodingJSON() throws { func testEncodingJSON() throws {
let buf: ByteBuffer = createProperBuffer().sizedByteBuffer let buf: ByteBuffer = createProperBuffer().sizedByteBuffer
let reference = try getRoot(buffer: buf)! let reference = try getRoot(buffer: buf)!
let json = reference.jsonString() let json = reference.jsonString()
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
json == json,
"{\"bar\": [1, 2, 3], \"bar3\": [1, 2, 3], \"bool\": true, \"bools\": [true, false, true, false], \"foo\": 100.0, \"mymap\": {\"foo\": \"Fred\"}, \"vec\": [-100, \"Fred\", 4.0, \"M\", false, 4.0]}" "{\"bar\": [1, 2, 3], \"bar3\": [1, 2, 3], \"bool\": true, \"bools\": [true, false, true, false], \"foo\": 100.0, \"mymap\": {\"foo\": \"Fred\"}, \"vec\": [-100, \"Fred\", 4.0, \"M\", false, 4.0]}"
) )
// swiftformat:enable all // swiftformat:enable all
@@ -39,15 +37,15 @@ struct FlexBuffersJSONTests {
with: data, with: data,
options: []) as! [String: Any] options: []) as! [String: Any]
#expect(decodedData["bar"] as! [Int] == [1, 2, 3]) XCTAssertEqual(decodedData["bar"] as! [Int], [1, 2, 3])
#expect(decodedData["bar3"] as! [Int] == [1, 2, 3]) XCTAssertEqual(decodedData["bar3"] as! [Int], [1, 2, 3])
let vec: [Any] = decodedData["vec"] as! [Any] let vec: [Any] = decodedData["vec"] as! [Any]
#expect(vec[0] as! Int == -100) XCTAssertEqual(vec[0] as! Int, -100)
#expect(vec[1] as! String == "Fred") XCTAssertEqual(vec[1] as! String, "Fred")
#expect(vec[2] as! Double == 4.0) XCTAssertEqual(vec[2] as! Double, 4.0)
#expect(vec[3] as! String == "M") XCTAssertEqual(vec[3] as! String, "M")
#expect(vec[4] as! Bool == false) XCTAssertEqual(vec[4] as! Bool, false)
#expect(vec[5] as! Double == 4.0) XCTAssertEqual(vec[5] as! Double, 4.0)
} }
} }
@@ -15,26 +15,22 @@
*/ */
import Common import Common
import Foundation import XCTest
import Testing
@testable import FlexBuffers @testable import FlexBuffers
struct FlexBuffersReaderTests { final class FlexBuffersReaderTests: XCTestCase {
@Test
func testReadingProperBuffer() throws { func testReadingProperBuffer() throws {
let buf: ByteBuffer = createProperBuffer().byteBuffer let buf: ByteBuffer = createProperBuffer().byteBuffer
try validate(buffer: buf) try validate(buffer: buf)
} }
@Test
func testReadingSizedBuffer() throws { func testReadingSizedBuffer() throws {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
try validate(buffer: buf) try validate(buffer: buf)
} }
@Test(.bug("https://github.com/google/flatbuffers/issues/8642"))
func testReset() throws { func testReset() throws {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -42,87 +38,87 @@ struct FlexBuffersReaderTests {
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray)) try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray))
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
fbx.reset() fbx.reset()
#expect(fbx.writerIndex == 0) XCTAssertEqual(fbx.writerIndex, 0)
#expect(fbx.capacity == 8) XCTAssertEqual(fbx.capacity, 8)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray)) try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray))
fbx.reset(keepingCapacity: true) fbx.reset(keepingCapacity: true)
#expect(fbx.writerIndex == 0) XCTAssertEqual(fbx.writerIndex, 0)
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray)) try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray))
#expect(fbx.capacity == 512) XCTAssertEqual(fbx.capacity, 512)
} }
private func validate(buffer buf: ByteBuffer) throws { private func validate(buffer buf: ByteBuffer) throws {
let reference = try getRoot(buffer: buf)! let reference = try getRoot(buffer: buf)!
#expect(reference.type == .map) XCTAssertEqual(reference.type, .map)
let map = reference.map! let map = reference.map!
#expect(map.count == 7) XCTAssertEqual(map.count, 7)
let vecRef = map["vec"]! let vecRef = map["vec"]!
#expect(vecRef.type == .vector) XCTAssertEqual(vecRef.type, .vector)
let vec = vecRef.vector! let vec = vecRef.vector!
#expect(vec.count == 6) XCTAssertEqual(vec.count, 6)
#expect(vec[0]?.type == .int) XCTAssertEqual(vec[0]?.type, .int)
#expect(vec[0]?.int == -100) XCTAssertEqual(vec[0]?.int, -100)
#expect(vec[1]?.type == .string) XCTAssertEqual(vec[1]?.type, .string)
#expect(vec[1]?.cString == "Fred") XCTAssertEqual(vec[1]?.cString, "Fred")
#expect(vec[1]?.int == nil) XCTAssertNil(vec[1]?.int)
#expect(vec[2]?.double == 4.0) XCTAssertEqual(vec[2]?.double, 4.0)
#expect(vec[3]?.type == .blob) XCTAssertTrue(vec[3]?.type == .blob)
let blob = vec[3]!.blob { pointer in let blob = vec[3]!.blob { pointer in
Array(pointer) Array(pointer)
} }
#expect(blob?.count == 1) XCTAssertEqual(blob?.count, 1)
#expect(blob?[0] == 77) XCTAssertEqual(blob?[0], 77)
#expect(vec[4]?.type == .bool) XCTAssertEqual(vec[4]?.type, .bool)
#expect(vec[4]?.bool == false) XCTAssertEqual(vec[4]?.bool, false)
#expect(vec[5]?.double == 4.0) // Shared with vec[2] XCTAssertEqual(vec[5]?.double, 4.0) // Shared with vec[2]
let barVec = map["bar"]!.typedVector! let barVec = map["bar"]!.typedVector!
#expect(barVec.count == 3) XCTAssertEqual(barVec.count, 3)
#expect(barVec[2]?.int == 3) XCTAssertEqual(barVec[2]?.int, 3)
#expect(barVec[2]?.asInt() == UInt8(3)) XCTAssertEqual(barVec[2]?.asInt(), UInt8(3))
let fixedVec = map["bar3"]!.fixedTypedVector! let fixedVec = map["bar3"]!.fixedTypedVector!
#expect(fixedVec.count == 3) XCTAssertEqual(fixedVec.count, 3)
#expect(fixedVec[2]?.int == 3) XCTAssertEqual(fixedVec[2]?.int, 3)
#expect(fixedVec[2]?.asInt() == UInt8(3)) XCTAssertEqual(fixedVec[2]?.asInt(), UInt8(3))
#expect(map["bool"]?.bool == true) XCTAssertEqual(map["bool"]?.bool, true)
let boolsVector = map["bools"]!.typedVector! let boolsVector = map["bools"]!.typedVector!
#expect(boolsVector.type == .bool) XCTAssertEqual(boolsVector.type, .bool)
#expect(boolsVector[0]?.bool == true) XCTAssertEqual(boolsVector[0]?.bool, true)
#expect(boolsVector[1]?.bool == false) XCTAssertEqual(boolsVector[1]?.bool, false)
let bools = [true, false, true, false] let bools = [true, false, true, false]
boolsVector.withUnsafeRawBufferPointer { buff in boolsVector.withUnsafeRawBufferPointer { buff in
for i in 0..<boolsVector.count { for i in 0..<boolsVector.count {
#expect(buff.load(fromByteOffset: i, as: Bool.self) == bools[i]) XCTAssertEqual(buff.load(fromByteOffset: i, as: Bool.self), bools[i])
} }
} }
#expect(map["foo"]?.double == 100) XCTAssertEqual(map["foo"]?.double, 100)
#expect(map["unknown"] == nil) XCTAssertNil(map["unknown"])
let mymap = map["mymap"]?.map let mymap = map["mymap"]?.map
// Check if both addresses used are the same for keys and strings // Check if both addresses used are the same for keys and strings
#expect(mymap?.keys[0]?.cString == map.keys[4]?.cString) XCTAssertEqual(mymap?.keys[0]?.cString, map.keys[4]?.cString)
map.keys[4]?.withUnsafeRawPointer { pointer in map.keys[4]?.withUnsafeRawPointer { pointer in
mymap?.keys[0]?.withUnsafeRawPointer { mymapPointer in mymap?.keys[0]?.withUnsafeRawPointer { mymapPointer in
#expect(pointer == mymapPointer) XCTAssertEqual(pointer, mymapPointer)
} }
} }
#expect(mymap?.values[0]?.cString == vec[1]?.cString) XCTAssertEqual(mymap?.values[0]?.cString, vec[1]?.cString)
vec[1]?.withUnsafeRawPointer { pointer in vec[1]?.withUnsafeRawPointer { pointer in
mymap?.values[0]?.withUnsafeRawPointer { mymapPointer in mymap?.values[0]?.withUnsafeRawPointer { mymapPointer in
#expect(pointer == mymapPointer) XCTAssertEqual(pointer, mymapPointer)
} }
} }
} }
@@ -131,7 +127,7 @@ struct FlexBuffersReaderTests {
#if os(macOS) #if os(macOS)
// Gets the current path of this test file then // Gets the current path of this test file then
// strips out the nested directories. // strips out the nested directories.
let filePath = URL(filePath: #filePath) let filePath = URL(filePath: #file)
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
@@ -16,12 +16,10 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Foundation import XCTest
import Testing
struct FlexBuffersStringTests { final class FlexBuffersStringTests: XCTestCase {
@Test
func testEncodingUnicodeString() { func testEncodingUnicodeString() {
let text = "プ画をみて✋" let text = "プ画をみて✋"
@@ -40,6 +38,6 @@ struct FlexBuffersStringTests {
return String(data: data, encoding: .unicode) return String(data: data, encoding: .unicode)
} }
#expect(builtString == text) XCTAssertEqual(builtString, text)
} }
} }
@@ -16,10 +16,9 @@
import Common import Common
import FlexBuffers import FlexBuffers
import Testing import XCTest
struct FlexBuffersWriterTests { final class FlexBuffersWriterTests: XCTestCase {
@Test
func testDeallocation() { func testDeallocation() {
let buf: ByteBuffer = { let buf: ByteBuffer = {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
@@ -29,13 +28,12 @@ struct FlexBuffersWriterTests {
}() }()
buf.withUnsafeBytes { buf.withUnsafeBytes {
#expect( XCTAssertEqual(
Array($0) == Array($0),
[5, 72, 101, 108, 108, 111, 0, 6, 20, 1]) [5, 72, 101, 108, 108, 111, 0, 6, 20, 1])
} }
} }
@Test
func testAddingVectorOfScalars() { func testAddingVectorOfScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -47,8 +45,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
10, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 10, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0,
0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 20, 0, 0, 0, 1, 41, 46, 2, 40, 1, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 20, 0, 0, 0, 1, 41, 46, 2, 40, 1,
@@ -57,7 +55,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testAddingVectorOfUnsignedScalars() { func testAddingVectorOfUnsignedScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -69,8 +66,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
10, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
@@ -81,7 +78,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testAddingVectorOfBools() { func testAddingVectorOfBools() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -93,14 +89,13 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[4, 1, 0, 1, 0, 1, 5, 144, 2, 40, 1]) [4, 1, 0, 1, 0, 1, 5, 144, 2, 40, 1])
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testSortingWithinMap() { func testSortingWithinMap() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.map { fbx.map {
@@ -111,8 +106,8 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
98, 111, 111, 108, 50, 0, 98, 111, 111, 108, 49, 0, 2, 7, 14, 2, 1, 2, 1, 0, 104, 104, 4, 98, 111, 111, 108, 50, 0, 98, 111, 111, 108, 49, 0, 2, 7, 14, 2, 1, 2, 1, 0, 104, 104, 4,
36, 1, 36, 1,
@@ -122,7 +117,6 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testSharingKeyWithinMap() { func testSharingKeyWithinMap() {
var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings) var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings)
fbx.map { fbx.map {
@@ -134,8 +128,8 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[ [
119, 101, 108, 99, 111, 109, 101, 0, 7, 119, 101, 108, 99, 111, 109, 101, 0, 3, 18, 19, 119, 101, 108, 99, 111, 109, 101, 0, 7, 119, 101, 108, 99, 111, 109, 101, 0, 3, 18, 19,
20, 3, 1, 3, 15, 16, 17, 20, 20, 20, 6, 36, 1, 20, 3, 1, 3, 15, 16, 17, 20, 20, 20, 6, 36, 1,
@@ -145,21 +139,19 @@ struct FlexBuffersWriterTests {
} }
} }
@Test
func testNestingVectorInMap() { func testNestingVectorInMap() {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
flexbufferGolden flexbufferGolden
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testAddingNil() { func testAddingNil() {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -173,15 +165,14 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
[118, 0, 1, 3, 1, 1, 1, 0, 0, 2, 36, 1] [118, 0, 1, 3, 1, 1, 1, 0, 0, 2, 36, 1]
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testAddingManually() { func testAddingManually() {
var fbx = FlexBuffersWriter( var fbx = FlexBuffersWriter(
initialSize: 8, initialSize: 8,
@@ -218,15 +209,14 @@ struct FlexBuffersWriterTests {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
flexbufferGolden flexbufferGolden
) )
// swiftformat:enable all // swiftformat:enable all
} }
} }
@Test
func testEncodingAllTypes() { func testEncodingAllTypes() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -250,8 +240,8 @@ struct FlexBuffersWriterTests {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
#expect( XCTAssertEqual(
Array($0) == Array($0),
allTypesGolden) allTypesGolden)
// swiftformat:enable all // swiftformat:enable all
} }
@@ -3,12 +3,12 @@
// swiftformat:disable all // swiftformat:disable all
#if canImport(Common) #if canImport(Common)
internal import Common @_implementationOnly import Common
#endif #endif
internal import FlatBuffers @_implementationOnly import FlatBuffers
internal struct Message: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { internal struct Message: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } static func validateVersion() { FlatBuffersVersion_25_12_19() }
internal var __buffer: ByteBuffer! { return _accessor.bb } internal var __buffer: ByteBuffer! { return _accessor.bb }
@@ -68,7 +68,7 @@ public struct BytesCount_Mutable: FlatBufferStruct, FlatbuffersVectorInitializab
} }
} }
public struct InternalMessage: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct InternalMessage: 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 }
@@ -148,7 +148,7 @@ public class InternalMessageT: NativeObject {
public func serialize() -> ByteBuffer { return serialize(type: InternalMessage.self) } public func serialize() -> ByteBuffer { return serialize(type: InternalMessage.self) }
} }
public struct Message: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker { public struct Message: 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 }
-1
View File
@@ -1774,7 +1774,6 @@ int FlatBufferTests(const std::string& tests_data_path) {
FixedLengthArrayJsonTest(tests_data_path, false); FixedLengthArrayJsonTest(tests_data_path, false);
FixedLengthArrayJsonTest(tests_data_path, true); FixedLengthArrayJsonTest(tests_data_path, true);
ReflectionTest(tests_data_path, flatbuf.data(), flatbuf.size()); ReflectionTest(tests_data_path, flatbuf.data(), flatbuf.size());
ForAllFieldsReverseTest(tests_data_path);
ParseProtoTest(tests_data_path); ParseProtoTest(tests_data_path);
EvolutionTest(tests_data_path); EvolutionTest(tests_data_path);
UnionDeprecationTest(tests_data_path); UnionDeprecationTest(tests_data_path);
+9 -3
View File
@@ -62,10 +62,16 @@ def flatc(
# Execute esbuild with the specified parameters # Execute esbuild with the specified parameters
def esbuild(input, output): def esbuild(input, output):
cmd = ["../../node_modules/.bin/esbuild", input, "--outfile=" + output] cmd = ["esbuild", input, "--outfile=" + output]
cmd += ["--format=cjs", "--bundle", "--external:flatbuffers"] cmd += ["--format=cjs", "--bundle", "--external:flatbuffers"]
check_call(cmd) check_call(cmd)
print("Removing node_modules/ directory...")
shutil.rmtree(Path(tests_path, "node_modules"), ignore_errors=True)
check_call(["npm", "install", "--silent"])
flatc( flatc(
options=[ options=[
"--ts", "--ts",
@@ -222,12 +228,12 @@ flatc(
) )
print("Running TypeScript Compiler...") print("Running TypeScript Compiler...")
check_call(["../../node_modules/.bin/tsc"]) check_call(["tsc"])
print( print(
"Running TypeScript Compiler in old node resolution mode for" "Running TypeScript Compiler in old node resolution mode for"
" no_import_ext..." " no_import_ext..."
) )
check_call(["../../node_modules/.bin/tsc", "-p", "./tsconfig.node.json"]) check_call(["tsc", "-p", "./tsconfig.node.json"])
NODE_CMD = ["node"] NODE_CMD = ["node"]
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"flatbuffers": "workspace:*" "flatbuffers": "../../"
} }
} }
+10
View File
@@ -0,0 +1,10 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
flatbuffers:
specifier: ../../
version: link:../..