Compare commits

..

15 Commits

Author SHA1 Message Date
Jakob Kordež
38df29380a [Dart] Fix namespace alias from union type (#9088)
* Fix namespace alias from union type

* Fix namespace alias from union type
2026-05-24 21:13:42 -04:00
Ali Sherif
1f438bd40f [Swift] Fix verifier accepting truncated scalar vectors (OOB read/write, RCE) (#9081) 2026-05-08 10:16:10 +02:00
mustiikhalil
392165432a [Swift] Migrate to use Swift Testing (#9076)
* Migrating from Xctests to swift testing

This migrates to the new Swift testing framework,
which would allow us to always use the latest tech
from swift moving forward.

* Updates flag to make sure that Wasm testing works
2026-05-07 21:49:41 -04:00
mustiikhalil
e6bbb3d22e [Swift] Migrate to swift 6.0 and Implements support gRPC v2 (#8983)
* Migrate to swift 6.0 & swift-gRPC 2.0

The following migrates to swift 6.0, and also
migrate to swift-grpc 2.0 that uses swift-nio
under the hood to provide nicer API and async await

Adds sendable to enum & update @_implementationOnly imports to use internal imports

* Address PR comments regarding misspelling & proper method naming.
2026-05-06 04:39:53 +02:00
Rifat Al Jubayer
a6979fe14a Fix logic inversion in FlexBuffers VerifyKey() (#9072)
VerifyKey() returns true on the first non-zero byte instead of
checking for a null terminator. This causes VerifyBuffer() to accept
FlexBuffers with non-null-terminated keys. Subsequent access to those
keys via strlen()/strcmp() reads out of bounds.

The condition if (*p++) should be if (!*p++) — return true
when a null terminator is found, not when any non-zero byte is found.

Confirmed with AddressSanitizer: heap-buffer-overflow in strlen()
after VerifyBuffer() returns true on a corrupted buffer.
2026-05-04 22:11:30 -04:00
Zen Dodd
bab10754d9 Stage the Python license file during builds (#9015)
Copy the repo-root LICENSE into the Python package directory for the duration of setup() so license_files = LICENSE remains valid without using deprecated parent-directory paths.

Remove the staged copy after the build completes.
2026-04-17 20:30:06 -04:00
Felix
ac7ef1176a Fix typo in generated header name (#9034) 2026-04-18 00:09:10 +00:00
Felix
d6444fb7fc Fix indention level for --no-python-gen-numpy (#9049) 2026-04-17 16:50:03 -04:00
Felix
e223d69b36 [Python] Extend GRPC Typing (#9007)
Extend function calls with optional type infos for checking
and discovering.

e838ba8a71/src/python/grpcio/grpc/__init__.py (L680)
2026-04-03 14:12:08 +00:00
Tulgaaaaaaaa
05cc7a2eff fix: correct operator precedence in ForAllFields reverse iteration (#8991)
* fix: correct operator precedence in ForAllFields reverse iteration

The expression `size() - i + 1` evaluates as `(size() - i) + 1` due to
left-to-right associativity, producing an out-of-bounds index when
reverse=true. For a vector of size N, the first iteration (i=0) accesses
index N+1, which is 2 past the last valid index.

Changed to `size() - (i + 1)` to match the correct implementation
already present in bfbs_gen.h:192.

Bug: CWE-125 (Out-of-bounds Read), CWE-783 (Operator Precedence Error)

* test: add ForAllFieldsReverseTest for reverse iteration correctness

Verify that ForAllFields with reverse=true iterates fields in
descending ID order. Tests both Stat (3 fields) and Monster
(many fields with non-sequential definition order) tables.

---------

Co-authored-by: Tulgaa <tulgaa.kek@gmail.com>
2026-04-02 10:14:27 +00:00
Noam ismach moshe
8a12183c3b Fix out-of-bounds vector access in StructDef::Deserialize (#8988)
* Fix out-of-bounds vector access in StructDef::Deserialize

* Fix syntax: use error_ instead of error()
2026-04-02 08:03:03 +00:00
Renzo
21b706b62d fix: swapped argument order in new_inconsistent_union calls (#9001) (#9010) 2026-04-02 07:05:58 +00:00
Tomasz Andrzejak
c5f151ab33 Add fallible try_* API for rust FlatBufferBuilder (#8918)
* Add fallible try_* API for FlatBufferBuilder

This is to support error propagation from Allocator trait. The Allocator
grow_downwards() method returns Result<(), Self::Error>, but
FlatBufferBuilder panics via .expect() when allocation fails instead of
propagating the error.

* Add rust fallible API docs
2026-04-02 06:49:51 +00:00
Björn Harrtell
3860f1cf7f [TS] Fixup TS test run at CI (#9004) 2026-03-30 13:32:24 +01:00
Thomas Köppe
4e582b0c1d [flexbuffers] Add "AlignedBlob", a version of "Blob" with explicit alignment. (#8993)
A blob is an array of bytes and has no intrinsic alignment (i.e. the
alignment is 1). The alignment of the existing flexbuffers blob is
solely affected by the width of the integer needed to store the blob's
size: that integer's width becomes the alignment of the blob.

The proposed AlignedBlob function here piggybacks on this effect and
simply uses a user-defined alignment for the width of the integer that
stores the blob's size; this automatically imparts that same alignment
on the blob itself. (The width is bounded below by the actual width
needed to store the blob's size.)

The ability to control the alignment of a blob is important for use
cases in which the blob itself stores structured data that we want to
access without further copies (e.g. other flatbuffer messages).
2026-03-23 10:28:03 -07:00
87 changed files with 4536 additions and 2095 deletions

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@v3 uses: microsoft/setup-msbuild@v2
- 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@v3 uses: microsoft/setup-msbuild@v2
- 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@v3 uses: microsoft/setup-msbuild@v2
- 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: ["5.10", "6.1", "6.2"] swift: ["6.0", "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 wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest --testing-library swift-testing
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 esbuild run: npm install -g pnpm
- name: deps - name: deps
run: pnpm i run: pnpm i
- name: compile - name: compile

View File

@@ -1,4 +1,4 @@
// swift-tools-version:5.10 // swift-tools-version:6.0
/* /*
* Copyright 2020 Google Inc. All rights reserved. * Copyright 2020 Google Inc. All rights reserved.
* *
@@ -36,14 +36,17 @@ 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,
@@ -52,7 +55,14 @@ 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] {
@@ -60,7 +70,12 @@ 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
} }
} }
@@ -72,7 +87,10 @@ extension Array where Element == PackageDescription.Target.Dependency {
#else #else
// Test only Dependency // Test only Dependency
[ [
.product(name: "GRPC", package: "grpc-swift"), .product(name: "GRPCCore", package: "grpc-swift-2"),
.product(
name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
"FlatBuffers", "FlatBuffers",
] ]
#endif #endif

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_generate.h" #include "monster_test_generated.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

View File

@@ -97,6 +97,61 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
*Note: That we never stored a `mana` value, so it will return the default.* *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

View File

@@ -0,0 +1,16 @@
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");
}

View File

@@ -1,4 +1,4 @@
// swift-tools-version:5.10 // swift-tools-version:6.2
/* /*
* Copyright 2020 Google Inc. All rights reserved. * Copyright 2020 Google Inc. All rights reserved.
* *
@@ -20,39 +20,43 @@ import PackageDescription
let package = Package( let package = Package(
name: "Greeter", name: "Greeter",
platforms: [ platforms: [
.iOS(.v12), .iOS(.v18),
.macOS(.v10_14), .macOS(.v15),
], ],
dependencies: [ dependencies: [
.package(path: "../../../../swift"), .package(path: "../../../.."),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0"), .package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.0.0"),
.package(
url: "https://github.com/grpc/grpc-swift-nio-transport.git",
from: "2.0.0"),
.package(
url: "https://github.com/apple/swift-argument-parser.git",
from: "1.5.0"),
], ],
targets: [ targets: [
// 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: "Model", name: "Models",
dependencies: [ dependencies: [
"GRPC", .product(name: "FlatBuffers", package: "flatbuffers"),
"FlatBuffers", .product(name: "GRPCCore", package: "grpc-swift-2"),
], .product(
path: "Sources/Model"), name: "GRPCNIOTransportHTTP2",
package: "grpc-swift-nio-transport"),
]),
// Client for the Greeter example // Client for the Greeter example
.target( .executableTarget(
name: "Client", name: "Commands",
dependencies: [ dependencies: [
"GRPC", .product(name: "GRPCCore", package: "grpc-swift-2"),
"Model", .product(
], name: "GRPCNIOTransportHTTP2",
path: "Sources/client"), package: "grpc-swift-nio-transport"),
.product(
// Server for the Greeter example name: "ArgumentParser",
.target( package: "swift-argument-parser"),
name: "Server", "Models",
dependencies: [ ]),
"GRPC",
"Model",
],
path: "Sources/server"),
]) ])

View File

@@ -0,0 +1,28 @@
/*
* 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])
}

View File

@@ -0,0 +1,121 @@
/*
* 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))
}
}
}

View File

@@ -0,0 +1,140 @@
/*
* 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")")
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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)")
}
}
}
}

View File

@@ -1,147 +0,0 @@
// Generated GRPC code for FlatBuffers swift!
/// The following code is generated by the Flatbuffers library which might not be in sync with grpc-swift
/// in case of an issue please open github issue, though it would be maintained
// swiftlint:disable all
// swiftformat:disable all
#if !os(Windows)
import Foundation
import GRPC
import NIO
import NIOHTTP1
import FlatBuffers
public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage {}
public extension GRPCFlatBufPayload {
init(serializedByteBuffer: inout NIO.ByteBuffer) throws {
self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: serializedByteBuffer.readableBytesView, count: serializedByteBuffer.readableBytes))
}
func serialize(into buffer: inout NIO.ByteBuffer) throws {
withUnsafeReadableBytes { buffer.writeBytes($0) }
}
}
extension Message: GRPCFlatBufPayload {}
/// Usage: instantiate models_GreeterServiceClient, then call methods of this protocol to make API calls.
public protocol models_GreeterClientProtocol: GRPCClient {
var serviceName: String { get }
var interceptors: models_GreeterClientInterceptorFactoryProtocol? { get }
func SayHello(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions?
) -> UnaryCall<Message<models_HelloRequest>, Message<models_HelloReply>>
func SayManyHellos(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions?,
handler: @escaping (Message<models_HelloReply>) -> Void
) -> ServerStreamingCall<Message<models_HelloRequest>, Message<models_HelloReply>>
}
extension models_GreeterClientProtocol {
public var serviceName: String { "models.Greeter" }
public func SayHello(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions? = nil
) -> UnaryCall<Message<models_HelloRequest>, Message<models_HelloReply>> {
return self.makeUnaryCall(
path: "/models.Greeter/SayHello",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSayHelloInterceptors() ?? []
)
}
public func SayManyHellos(
_ request: Message<models_HelloRequest>
, callOptions: CallOptions? = nil,
handler: @escaping (Message<models_HelloReply>) -> Void
) -> ServerStreamingCall<Message<models_HelloRequest>, Message<models_HelloReply>> {
return self.makeServerStreamingCall(
path: "/models.Greeter/SayManyHellos",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSayManyHellosInterceptors() ?? [],
handler: handler
)
}
}
public protocol models_GreeterClientInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when invoking 'SayHello'.
func makeSayHelloInterceptors() -> [ClientInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
/// - Returns: Interceptors to use when invoking 'SayManyHellos'.
func makeSayManyHellosInterceptors() -> [ClientInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
}
public final class models_GreeterServiceClient: models_GreeterClientProtocol {
public let channel: GRPCChannel
public var defaultCallOptions: CallOptions
public var interceptors: models_GreeterClientInterceptorFactoryProtocol?
public init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: models_GreeterClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
}
}
public protocol models_GreeterProvider: CallHandlerProvider {
var interceptors: models_GreeterServerInterceptorFactoryProtocol? { get }
func SayHello(request: Message<models_HelloRequest>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<models_HelloReply>>
func SayManyHellos(request: Message<models_HelloRequest>, context: StreamingResponseCallContext<Message<models_HelloReply>>) -> EventLoopFuture<GRPCStatus>
}
public extension models_GreeterProvider {
var serviceName: Substring { return "models.Greeter" }
func handle(method name: Substring, context: CallHandlerContext) -> GRPCServerHandlerProtocol? {
switch name {
case "SayHello":
return UnaryServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<models_HelloRequest>>(),
responseSerializer: GRPCPayloadSerializer<Message<models_HelloReply>>(),
interceptors: self.interceptors?.makeSayHelloInterceptors() ?? [],
userFunction: self.SayHello(request:context:))
case "SayManyHellos":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<models_HelloRequest>>(),
responseSerializer: GRPCPayloadSerializer<Message<models_HelloReply>>(),
interceptors: self.interceptors?.makeSayManyHellosInterceptors() ?? [],
userFunction: self.SayManyHellos(request:context:))
default: return nil;
}
}
}
public protocol models_GreeterServerInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when handling 'SayHello'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSayHelloInterceptors() -> [ServerInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
/// - Returns: Interceptors to use when handling 'SayManyHellos'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSayManyHellosInterceptors() -> [ServerInterceptor<Message<models_HelloRequest>, Message<models_HelloReply>>]
}
#endif

View File

@@ -0,0 +1,572 @@
// 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

View File

@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct models_HelloReply: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable { public struct models_HelloResponse: FlatBufferVerifiableTable, FlatbuffersVectorInitializable {
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_HelloReply: FlatBufferTable, FlatbuffersVectorInitializable
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 startHelloReply(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) } public static func startHelloResponse(_ 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 endHelloReply(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } public static func endHelloResponse(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
public static func createHelloReply( public static func createHelloResponse(
_ fbb: inout FlatBufferBuilder, _ fbb: inout FlatBufferBuilder,
messageOffset message: Offset = Offset() messageOffset message: Offset = Offset()
) -> Offset { ) -> Offset {
let __start = models_HelloReply.startHelloReply(&fbb) let __start = models_HelloResponse.startHelloResponse(&fbb)
models_HelloReply.add(message: message, &fbb) models_HelloResponse.add(message: message, &fbb)
return models_HelloReply.endHelloReply(&fbb, start: __start) return models_HelloResponse.endHelloResponse(&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_HelloReply: FlatBufferTable, FlatbuffersVectorInitializable
} }
} }
extension models_HelloReply: Encodable { extension models_HelloResponse: Encodable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case message = "message" case message = "message"
} }
@@ -53,7 +53,7 @@ extension models_HelloReply: Encodable {
} }
} }
public struct models_HelloRequest: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable { public struct models_HelloRequest: FlatBufferVerifiableTable, FlatbuffersVectorInitializable {
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 }

View File

@@ -1,108 +0,0 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import FlatBuffers
import GRPC
import Logging
import Model
import NIO
// Quieten the logs.
LoggingSystem.bootstrap {
var handler = StreamLogHandler.standardOutput(label: $0)
handler.logLevel = .critical
return handler
}
func greet(name: String, client greeter: models_GreeterServiceClient) {
// Form the request with the name, if one was provided.
var builder = FlatBufferBuilder()
let nameOff = builder.create(string: name)
let root = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: nameOff)
builder.finish(offset: root)
// Make the RPC call to the server.
let sayHello =
greeter
.SayHello(Message<models_HelloRequest>(builder: &builder))
// wait() on the response to stop the program from exiting before the response is received.
do {
let response = try sayHello.response.wait()
print("Greeter SayHello received: \(response.object.message ?? "Unknown")")
} catch {
print("Greeter failed: \(error)")
}
let surname = builder.create(string: name)
let manyRoot = models_HelloRequest.createHelloRequest(
&builder,
nameOffset: surname)
builder.finish(offset: manyRoot)
let call = greeter.SayManyHellos(Message(builder: &builder)) { message in
print(
"Greeter SayManyHellos received: \(message.object.message ?? "Unknown")")
}
let status = try! call.status.recover { _ in .processingError }.wait()
if status.code != .ok {
print("RPC failed: \(status)")
}
}
func main(args: [String]) {
// arg0 (dropped) is the program name. We expect arg1 to be the port, and arg2 (optional) to be
// the name sent in the request.
let arg1 = args.dropFirst(1).first
let arg2 = args.dropFirst(2).first
switch (arg1.flatMap(Int.init), arg2) {
case (.none, _):
print("Usage: PORT [NAME]")
exit(1)
case (.some(let port), let name):
// Setup an `EventLoopGroup` for the connection to run on.
//
// See: https://github.com/apple/swift-nio#eventloops-and-eventloopgroups
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
// Make sure the group is shutdown when we're done with it.
defer {
try! group.syncShutdownGracefully()
}
// Configure the channel, we're not using TLS so the connection is `insecure`.
let channel = ClientConnection.insecure(group: group)
.connect(host: "localhost", port: port)
// Close the connection when we're done with it.
defer {
try! channel.close().wait()
}
// Provide the connection to the generated client.
let greeter = models_GreeterServiceClient(channel: channel)
// Do the greeting.
greet(name: name ?? "FlatBuffers!", client: greeter)
}
}
main(args: CommandLine.arguments)

View File

@@ -1,97 +0,0 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import FlatBuffers
import GRPC
import Logging
import Model
import NIO
class Greeter: models_GreeterProvider {
var interceptors: models_GreeterServerInterceptorFactoryProtocol?
let greetings: [String]
init() {
greetings = ["Hi", "Hallo", "Ciao"]
}
func SayHello(
request: Message<models_HelloRequest>,
context: StatusOnlyCallContext)
-> EventLoopFuture<Message<models_HelloReply>>
{
let recipient = request.object.name ?? "Stranger"
var builder = FlatBufferBuilder()
let off = builder.create(string: "Hello \(recipient)")
let root = models_HelloReply.createHelloReply(&builder, messageOffset: off)
builder.finish(offset: root)
return context.eventLoop
.makeSucceededFuture(Message<models_HelloReply>(builder: &builder))
}
func SayManyHellos(
request: Message<models_HelloRequest>,
context: StreamingResponseCallContext<Message<models_HelloReply>>)
-> EventLoopFuture<GRPCStatus>
{
for name in greetings {
var builder = FlatBufferBuilder()
let off =
builder
.create(string: "\(name) \(request.object.name ?? "Unknown")")
let root = models_HelloReply.createHelloReply(
&builder,
messageOffset: off)
builder.finish(offset: root)
_ = context.sendResponse(Message<models_HelloReply>(builder: &builder))
}
return context.eventLoop.makeSucceededFuture(.ok)
}
}
// Quieten the logs.
LoggingSystem.bootstrap {
var handler = StreamLogHandler.standardOutput(label: $0)
handler.logLevel = .critical
return handler
}
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
// Create some configuration for the server:
let configuration = Server.Configuration(
target: .hostAndPort("localhost", 0),
eventLoopGroup: group,
serviceProviders: [Greeter()])
// Start the server and print its address once it has started.
let server = Server.start(configuration: configuration)
server.map {
$0.channel.localAddress
}.whenSuccess { address in
print("server started on port \(address!.port!)")
}
// Wait on the server's `onClose` future to stop the program from exiting.
_ = try server.flatMap {
$0.onClose
}.wait()

View File

@@ -172,6 +172,7 @@ 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";
@@ -183,14 +184,22 @@ class StubGenerator : public BaseGenerator {
imports->Import(ModuleFor(method->response), response); imports->Import(ModuleFor(method->response), response);
} }
ss << " def " << method->name << "(self, "; ss << " def " << method->name << "(\n";
ss << " self,\n";
if (ClientStreaming(method)) { if (ClientStreaming(method)) {
imports->Import("typing"); ss << " request_iterator: typing.Iterator[" << request << "]\n";
ss << "request_iterator: typing.Iterator[" << request << "]";
} else { } else {
ss << "request: " << request; ss << " request: " << request << ",\n";
} }
ss << ") -> ";
ss << " timeout: float | None = None,\n";
// https://github.com/python/typeshed/blob/ccf9411fb1f5bee2a8e3d278889de17a08f7bbe3/stubs/grpcio/grpc/__init__.pyi#L37
ss << " metadata: typing.Sequence[tuple[str, typing.Union[str, bytes]]] | None = None,\n";
ss << " credentials: grpc.CallCredentials | None = None,\n";
ss << " wait_for_ready: bool | None = None,\n";
ss << " compression: grpc.Compression | None = None\n";
ss << " ) -> ";
if (ServerStreaming(method)) { 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

View File

@@ -1207,11 +1207,20 @@ 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 CreateBlob(v.data(), v.size(), 0, FBT_BLOB); return Blob(v.data(), v.size());
} }
void Blob(const char* key, const void* data, size_t len) { void Blob(const char* key, const void* data, size_t len) {
@@ -1693,11 +1702,16 @@ class Builder FLATBUFFERS_FINAL_CLASS {
size_t CreateBlob(const void* data, size_t len, size_t trailing, Type type) { size_t CreateBlob(const void* data, size_t len, size_t trailing, Type type) {
auto bit_width = WidthU(len); auto bit_width = WidthU(len);
auto byte_width = Align(bit_width); return CreateAlignedBlob(data, len, trailing, type, bit_width);
}
size_t CreateAlignedBlob(const void* data, size_t len, size_t trailing,
Type type, BitWidth alignment) {
auto byte_width = Align(alignment);
Write<uint64_t>(len, byte_width); 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, bit_width)); stack_.push_back(Value(static_cast<uint64_t>(sloc), type, alignment));
return sloc; return sloc;
} }
@@ -1962,7 +1976,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
pnpm-lock.yaml generated
View File

@@ -33,6 +33,12 @@ 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
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,2 @@
packages:
- tests/ts

View File

@@ -12,33 +12,54 @@
# 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(
name='flatbuffers', _THIS_DIR = Path(__file__).resolve().parent
version='25.12.19', _ROOT_LICENSE = _THIS_DIR.parent / 'LICENSE'
license='Apache 2.0', _LOCAL_LICENSE = _THIS_DIR / 'LICENSE'
author='Derek Bailey',
author_email='derekbailey@google.com',
url='https://google.github.io/flatbuffers/', def _stage_license_file():
long_description=( if _LOCAL_LICENSE.exists() or not _ROOT_LICENSE.exists():
'Python runtime library for use with the ' return False
'`Flatbuffers <https://google.github.io/flatbuffers/>`_ ' shutil.copyfile(_ROOT_LICENSE, _LOCAL_LICENSE)
'serialization format.' return True
),
packages=['flatbuffers'], _remove_staged_license = _stage_license_file()
include_package_data=True,
requires=[], try:
description='The FlatBuffers serialization format for Python', setup(
classifiers=[ name='flatbuffers',
'Intended Audience :: Developers', version='25.12.19',
'Operating System :: OS Independent', license='Apache 2.0',
'Programming Language :: Python', author='Derek Bailey',
'Programming Language :: Python :: 3', author_email='derekbailey@google.com',
'Topic :: Software Development :: Libraries :: Python Modules', url='https://google.github.io/flatbuffers/',
], long_description=(
project_urls={ 'Python runtime library for use with the '
'Documentation': 'https://google.github.io/flatbuffers/', '`Flatbuffers <https://google.github.io/flatbuffers/>`_ '
'Source': 'https://github.com/google/flatbuffers', 'serialization format.'
}, ),
) packages=['flatbuffers'],
include_package_data=True,
requires=[],
description='The FlatBuffers serialization format for Python',
classifiers=[
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
],
project_urls={
'Documentation': 'https://google.github.io/flatbuffers/',
'Source': 'https://github.com/google/flatbuffers',
},
)
finally:
if _remove_staged_license and _LOCAL_LICENSE.exists():
_LOCAL_LICENSE.unlink()

View File

@@ -337,22 +337,43 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.strings_pool.clear(); self.strings_pool.clear();
} }
/// Push a Push'able value onto the front of the in-progress data. /// Fallible version of [`push`](Self::push).
///
/// This function uses traits to provide a unified API for writing
/// scalars, tables, vectors, and WIPOffsets.
#[inline] #[inline]
pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> { pub fn try_push<P: Push>(&mut self, x: P) -> Result<WIPOffset<P::Output>, A::Error> {
let sz = P::size(); let sz = P::size();
self.align(sz, P::alignment()); self.align(sz, P::alignment())?;
self.make_space(sz); self.make_space(sz)?;
{ {
let (dst, rest) = self.allocator[self.head.range_to_end()].split_at_mut(sz); let (dst, rest) = self.allocator[self.head.range_to_end()].split_at_mut(sz);
// Safety: // Safety:
// Called make_space above // Called make_space above
unsafe { x.push(dst, rest.len()) }; unsafe { x.push(dst, rest.len()) };
} }
WIPOffset::new(self.used_space() as UOffsetT) Ok(WIPOffset::new(self.used_space() as UOffsetT))
}
/// Push a Push'able value onto the front of the in-progress data.
///
/// This function uses traits to provide a unified API for writing
/// scalars, tables, vectors, and WIPOffsets.
#[inline]
pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> {
self.try_push(x).expect("Flatbuffer allocation failure")
}
/// Fallible version of [`push_slot`](Self::push_slot).
#[inline]
pub fn try_push_slot<X: Push + PartialEq>(
&mut self,
slotoff: VOffsetT,
x: X,
default: X,
) -> Result<(), A::Error> {
self.assert_nested("push_slot");
if x != default || self.force_defaults {
self.try_push_slot_always(slotoff, x)?;
}
Ok(())
} }
/// Push a Push'able value onto the front of the in-progress data, and /// Push a Push'able value onto the front of the in-progress data, and
@@ -360,19 +381,29 @@ 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.assert_nested("push_slot"); self.try_push_slot(slotoff, x, default)
if x != default || self.force_defaults { .expect("Flatbuffer allocation failure")
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.assert_nested("push_slot_always"); self.try_push_slot_always(slotoff, x)
let off = self.push(x); .expect("Flatbuffer allocation failure")
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
@@ -397,6 +428,22 @@ 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.
@@ -405,14 +452,19 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
&mut self, &mut self,
off: WIPOffset<TableUnfinishedWIPOffset>, off: WIPOffset<TableUnfinishedWIPOffset>,
) -> WIPOffset<TableFinishedWIPOffset> { ) -> WIPOffset<TableFinishedWIPOffset> {
self.assert_nested("end_table"); self.try_end_table(off)
.expect("Flatbuffer allocation failure")
}
let o = self.write_vtable(off); /// Fallible version of [`start_vector`](Self::start_vector).
#[inline]
self.nested = false; pub fn try_start_vector<T: Push>(&mut self, num_items: usize) -> Result<(), A::Error> {
self.field_locs.clear(); self.assert_not_nested(
"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.
@@ -424,11 +476,20 @@ 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.assert_not_nested( self.try_start_vector::<T>(num_items)
"start_vector can not be called when a table or vector is under construction", .expect("Flatbuffer allocation failure")
); }
self.nested = true;
self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET)); /// Fallible version of [`end_vector`](Self::end_vector).
#[inline]
pub fn try_end_vector<T: Push>(
&mut self,
num_elems: usize,
) -> Result<WIPOffset<Vector<'fbb, T>>, A::Error> {
self.assert_nested("end_vector");
let o = self.try_push::<UOffsetT>(num_elems as UOffsetT)?;
self.nested = false;
Ok(WIPOffset::new(o.value()))
} }
/// End a Vector write. /// End a Vector write.
@@ -439,10 +500,31 @@ 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.assert_nested("end_vector"); self.try_end_vector::<T>(num_elems)
self.nested = false; .expect("Flatbuffer allocation failure")
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.
@@ -452,26 +534,20 @@ 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.assert_not_nested( self.try_create_shared_string(s)
"create_shared_string can not be called when a table or vector is under construction", .expect("Flatbuffer allocation failure")
);
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
} }
/// Create a utf8 string, and de-duplicate if already created. /// Fallible version of [`create_shared_string`](Self::create_shared_string).
/// ///
/// 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 create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> { pub fn try_create_shared_string<'a: 'b, 'b>(
&'a mut self,
s: &'b str,
) -> Result<WIPOffset<&'fbb str>, A::Error> {
self.assert_not_nested( self.assert_not_nested(
"create_shared_string can not be called when a table or vector is under construction", "create_shared_string can not be called when a table or vector is under construction",
); );
@@ -494,52 +570,83 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
}); });
match found { match found {
Ok(index) => self.strings_pool[index], Ok(index) => Ok(self.strings_pool[index]),
Err(index) => { Err(index) => {
let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value()); let address =
WIPOffset::new(self.try_create_byte_string(s.as_bytes())?.value());
self.strings_pool.insert(index, address); self.strings_pool.insert(index, address);
address Ok(address)
} }
} }
} }
/// Create a utf8 string, and de-duplicate if already created.
///
/// Uses a sorted Vec with binary search to track previously written
/// strings when in `no_std` mode.
#[cfg(not(feature = "std"))]
#[inline]
pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
self.try_create_shared_string(s)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_string`](Self::create_string).
#[inline]
pub fn try_create_string<'a: 'b, 'b>(
&'a mut self,
s: &'b str,
) -> Result<WIPOffset<&'fbb str>, A::Error> {
self.assert_not_nested(
"create_string can not be called when a table or vector is under construction",
);
Ok(WIPOffset::new(
self.try_create_byte_string(s.as_bytes())?.value(),
))
}
/// Create a utf8 string. /// 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_string can not be called when a table or vector is under construction", "create_byte_string can not be called when a table or vector is under construction",
); );
WIPOffset::new(self.create_byte_string(s.as_bytes()).value()) self.align(data.len() + 1, PushAlignment::new(SIZE_UOFFSET))?;
self.try_push(0u8)?;
self.push_bytes_unprefixed(data)?;
self.try_push(data.len() as UOffsetT)?;
Ok(WIPOffset::new(self.used_space() as UOffsetT))
} }
/// Create a zero-terminated byte vector. /// 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.assert_not_nested( self.try_create_byte_string(data)
"create_byte_string can not be called when a table or vector is under construction", .expect("Flatbuffer allocation failure")
);
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)
} }
/// Create a vector of Push-able objects. /// Fallible version of [`create_vector`](Self::create_vector).
///
/// 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 create_vector<'a: 'b, 'b, T: Push + 'b>( pub fn try_create_vector<'a: 'b, 'b, T: Push + 'b>(
&'a mut self, &'a mut self,
items: &'b [T], items: &'b [T],
) -> WIPOffset<Vector<'fbb, T::Output>> { ) -> Result<WIPOffset<Vector<'fbb, T::Output>>, A::Error> {
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();
@@ -553,7 +660,38 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
unsafe { item.push(out, written_len) }; unsafe { item.push(out, written_len) };
} }
WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value()) Ok(WIPOffset::new(
self.try_push::<UOffsetT>(items.len() as UOffsetT)?.value(),
))
}
/// Create a vector of Push-able objects.
///
/// Speed-sensitive users may wish to reduce memory usage by creating the
/// vector manually: use `start_vector`, `push`, and `end_vector`.
#[inline]
pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
&'a mut self,
items: &'b [T],
) -> WIPOffset<Vector<'fbb, T::Output>> {
self.try_create_vector(items)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`create_vector_from_iter`](Self::create_vector_from_iter).
#[inline]
pub fn try_create_vector_from_iter<T: Push>(
&mut self,
items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
) -> Result<WIPOffset<Vector<'fbb, T::Output>>, A::Error> {
let elem_size = T::size();
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET))?;
let mut actual = 0;
for item in items.rev() {
self.try_push(item)?;
actual += 1;
}
Ok(WIPOffset::new(self.try_push::<UOffsetT>(actual)?.value()))
} }
/// Create a vector of Push-able objects. /// Create a vector of Push-able objects.
@@ -565,14 +703,8 @@ 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>> {
let elem_size = T::size(); self.try_create_vector_from_iter(items)
self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET)); .expect("Flatbuffer allocation failure")
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.
@@ -635,13 +767,34 @@ 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.finish_with_opts(root, file_identifier, true); self.try_finish_size_prefixed(root, file_identifier)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`finish`](Self::finish).
#[inline]
pub fn try_finish<T>(
&mut self,
root: WIPOffset<T>,
file_identifier: Option<&str>,
) -> Result<(), A::Error> {
self.finish_with_opts(root, file_identifier, false)
} }
/// Finalize the FlatBuffer by: aligning it, pushing an optional file /// Finalize the FlatBuffer by: aligning it, pushing an optional file
@@ -650,7 +803,14 @@ 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.finish_with_opts(root, file_identifier, false); self.try_finish(root, file_identifier)
.expect("Flatbuffer allocation failure")
}
/// Fallible version of [`finish_minimal`](Self::finish_minimal).
#[inline]
pub fn try_finish_minimal<T>(&mut self, root: WIPOffset<T>) -> Result<(), A::Error> {
self.finish_with_opts(root, None, false)
} }
/// Finalize the FlatBuffer by: aligning it and marking the internal state /// Finalize the FlatBuffer by: aligning it and marking the internal state
@@ -658,7 +818,8 @@ 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.finish_with_opts(root, None, false); self.try_finish_minimal(root)
.expect("Flatbuffer allocation failure")
} }
#[inline] #[inline]
@@ -676,13 +837,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>,
) -> WIPOffset<VTableWIPOffset> { ) -> Result<WIPOffset<VTableWIPOffset>, A::Error> {
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.push::<UOffsetT>(0xF0F0_F0F0).value()); WIPOffset::new(self.try_push::<UOffsetT>(0xF0F0_F0F0)?.value());
// Layout of the data this function will create when a new vtable is // Layout of the data this function will create when a new vtable is
// needed. // needed.
@@ -725,7 +886,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();
@@ -750,13 +911,15 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
} }
} }
let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)]; let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)];
let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| { let found = self
let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize; .written_vtable_revpos
// Safety: .binary_search_by(|old_vtable_revpos: &UOffsetT| {
// Already written vtables are valid by construction let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize;
let old_vtable = unsafe { VTable::init(&self.allocator, old_vtable_pos) }; // Safety:
new_vt_bytes.cmp(old_vtable.as_bytes()) // Already written vtables are valid by construction
}); let old_vtable = unsafe { VTable::init(&self.allocator, old_vtable_pos) };
new_vt_bytes.cmp(old_vtable.as_bytes())
});
let final_vtable_revpos = match found { 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.
@@ -794,17 +957,18 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
self.field_locs.clear(); self.field_locs.clear();
object_revloc_to_vtable Ok(object_revloc_to_vtable)
} }
// Only call this when you know it is safe to double the size of the buffer. // Only call this when you know it is safe to double the size of the buffer.
#[inline] #[inline]
fn grow_allocator(&mut self) { fn grow_allocator(&mut self) -> Result<(), A::Error> {
let starting_active_size = self.used_space(); let starting_active_size = self.used_space();
self.allocator.grow_downwards().expect("Flatbuffer allocation failure"); self.allocator.grow_downwards()?;
let ending_active_size = self.used_space(); 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*
@@ -814,7 +978,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",
@@ -827,34 +991,40 @@ 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() { FILE_IDENTIFIER_LENGTH } else { 0 }; let c = if file_identifier.is_some() {
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.push(root); self.try_push(root)?;
if size_prefixed { if size_prefixed {
let sz = self.used_space() as UOffsetT; let sz = self.used_space() as UOffsetT;
self.push::<UOffsetT>(sz); self.try_push::<UOffsetT>(sz)?;
} }
self.finished = true; self.finished = true;
Ok(())
} }
#[inline] #[inline]
fn align(&mut self, len: usize, alignment: PushAlignment) { fn align(&mut self, len: usize, alignment: PushAlignment) -> Result<(), A::Error> {
self.track_min_align(alignment.value()); 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]
@@ -863,31 +1033,34 @@ impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
} }
#[inline] #[inline]
fn push_bytes_unprefixed(&mut self, x: &[u8]) -> UOffsetT { fn push_bytes_unprefixed(&mut self, x: &[u8]) -> Result<UOffsetT, A::Error> {
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);
n.to_forward_index(&self.allocator) as UOffsetT Ok(n.to_forward_index(&self.allocator) as UOffsetT)
} }
#[inline] #[inline]
fn make_space(&mut self, want: usize) -> ReverseIndex { fn make_space(&mut self, want: usize) -> Result<ReverseIndex, A::Error> {
self.ensure_capacity(want); self.ensure_capacity(want)?;
self.head -= want; self.head -= want;
self.head Ok(self.head)
} }
#[inline] #[inline]
fn ensure_capacity(&mut self, want: usize) -> usize { fn ensure_capacity(&mut self, want: usize) -> Result<usize, A::Error> {
if self.unused_ready_space() >= want { if self.unused_ready_space() >= want {
return want; return Ok(want);
} }
assert!(want <= FLATBUFFERS_MAX_BUFFER_SIZE, "cannot grow buffer beyond 2 gigabytes"); assert!(
want <= FLATBUFFERS_MAX_BUFFER_SIZE,
"cannot grow buffer beyond 2 gigabytes"
);
while self.unused_ready_space() < want { while self.unused_ready_space() < want {
self.grow_allocator(); self.grow_allocator()?;
} }
want Ok(want)
} }
#[inline] #[inline]
fn unused_ready_space(&self) -> usize { fn unused_ready_space(&self) -> usize {
@@ -1129,4 +1302,111 @@ 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");
}
} }

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(
key_field_name.into(),
val_field_name.into(), val_field_name.into(),
key_field_name.into(),
), ),
} }
} }

View File

@@ -397,8 +397,8 @@ fn verify_union<'a, 'b, 'c>(
} }
} else { } else {
return InvalidFlatbuffer::new_inconsistent_union( return InvalidFlatbuffer::new_inconsistent_union(
format!("{}_type", field.name()),
field.name().to_string(), field.name().to_string(),
format!("{}_type", field.name()),
)?; )?;
} }

View File

@@ -161,7 +161,7 @@ public struct MyGame_Sample_Vec3_Mutable: FlatBufferStruct, FlatbuffersVectorIni
} }
} }
public struct MyGame_Sample_Monster: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Sample_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, ObjectAPIPacker {
static func validateVersion() { FlatBuffersVersion_25_12_19() } 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Sample_Weapon: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -20,6 +20,7 @@ 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",
@@ -54,8 +55,8 @@ def GenerateGRPCExamples():
"--swift", "--swift",
"--gen-json-emit", "--gen-json-emit",
], ],
schema=greeter_schema, schema=greeter_schema_v2,
cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Model"), cwd=Path(grpc_examples_path, "swift/Greeter/Sources/Models"),
) )
flatc( flatc(

View File

@@ -654,34 +654,15 @@ class DartGenerator : public BaseGenerator {
std::string NamespaceAliasFromUnionType(Namespace* root_namespace, std::string NamespaceAliasFromUnionType(Namespace* root_namespace,
const Type& type) { const Type& type) {
const std::vector<std::string> qualified_name_parts = const Namespace& type_namespace = *type.struct_def->defined_namespace;
type.struct_def->defined_namespace->components; if (root_namespace->components == type_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);
} }
std::string ns; const std::string ns = namer_.Namespace(type_namespace);
return ns.empty()
for (auto it = qualified_name_parts.begin(); ? namer_.Type(*type.struct_def)
it != qualified_name_parts.end(); ++it) { : ImportAliasName(ns) + "." + namer_.Type(*type.struct_def);
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(

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(4) + field_field + " = builder.EndVector()"; code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
} }
} }

View File

@@ -170,9 +170,8 @@ 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", parser_.opts.swift_implementation_only code_.SetValue("IMPLEMENTONLY",
? "@_implementationOnly " parser_.opts.swift_implementation_only ? "internal " : "");
: "");
code_ += "#if canImport(Common)"; code_ += "#if canImport(Common)";
code_ += "{{IMPLEMENTONLY}}import Common"; code_ += "{{IMPLEMENTONLY}}import Common";
code_ += "#endif"; code_ += "#endif";
@@ -549,13 +548,14 @@ 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}}: "
"FlatBuffer{{OBJECTTYPE}}, FlatbuffersVectorInitializable\\"; "{{PROTOCOL}}, 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";

View File

@@ -4132,7 +4132,15 @@ 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++) indexes[of.Get(i)->id()] = i; for (uoffset_t i = 0; i < of.size(); i++) {
uint16_t field_id = of.Get(i)->id();
if (field_id >= of.size()) {
parser.error_ = "Field ID " + std::to_string(field_id) +
" exceeds field count " + std::to_string(of.size());
return false;
}
indexes[field_id] = i;
}
size_t tmp_struct_size = 0; 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]);

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]));
} }
} }

View File

@@ -20,7 +20,7 @@ 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 { public struct ByteBuffer: @unchecked Sendable {
/// 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)
@@ -30,7 +30,7 @@ public struct ByteBuffer {
enum Blob { enum Blob {
#if !os(WASI) #if !os(WASI)
case data(Data) case data(Data)
case bytes(ContiguousBytes) case bytes(any ContiguousBytes)
#endif #endif
case byteBuffer(_InternalByteBuffer) case byteBuffer(_InternalByteBuffer)

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 { public protocol Enum: Sendable {
/// 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

View File

@@ -45,7 +45,7 @@ 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 var finished = false private(set) 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
private var serializeDefaults: Bool private var serializeDefaults: Bool
@@ -488,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: ContiguousBytes) -> Offset { mutating public func createVector(bytes: any 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)

View File

@@ -20,6 +20,8 @@ import Foundation
/// 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 {} 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
public protocol FlatbuffersInitializable { public protocol FlatbuffersInitializable {
@@ -35,6 +37,8 @@ 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

View File

@@ -16,50 +16,52 @@
import Foundation import Foundation
/// FlatBufferGRPCMessage protocol that should allow us to invoke enum FlatbuffersGRPCError: Error {
/// initializers directly from the GRPC generated code case finishedNotCalledOnBuilder
public protocol FlatBufferGRPCMessage {
/// Size of readable bytes in the buffer
var size: Int { get }
init(byteBuffer: ByteBuffer)
@discardableResult
@inline(__always)
func withUnsafeReadableBytes<T>(
_ body: (UnsafeRawBufferPointer) throws
-> T) rethrows -> T
} }
/// Message is a wrapper around Buffers to to able to send Flatbuffers `Buffers` through the public protocol GRPCVerifiableMessage<Message> {
/// GRPC library associatedtype Message
public struct Message<T: FlatBufferTable>: FlatBufferGRPCMessage {
internal var buffer: ByteBuffer
/// Returns the an object of type T that would be read from the buffer init(pointer: UnsafeRawBufferPointer)
public var object: T { init(byteBuffer: ByteBuffer)
T.init(
buffer, func decode() throws -> Message
o: Int32(buffer.read(def: UOffset.self, position: buffer.reader)) &+ func withUnsafeReadableBytes<Data>(
Int32(buffer.reader)) _ body: (UnsafeRawBufferPointer) throws
} -> Data) rethrows -> Data
}
public struct GRPCMessage<
Table: FlatBufferVerifiableTable
>: Sendable, GRPCVerifiableMessage {
public typealias Message = Table
private let buffer: ByteBuffer
public var size: Int { Int(buffer.size) } public var size: Int { Int(buffer.size) }
/// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over public init(pointer: UnsafeRawBufferPointer) {
/// GRPC buffer = ByteBuffer(
/// - Parameter byteBuffer: Flatbuffer ByteBuffer object copyingMemoryBound: pointer.baseAddress!,
capacity: pointer.count)
}
public init(builder: inout FlatBufferBuilder) throws {
guard builder.finished else {
throw FlatbuffersGRPCError.finishedNotCalledOnBuilder
}
buffer = builder.sizedBuffer
}
public init(byteBuffer: ByteBuffer) { public init(byteBuffer: ByteBuffer) {
buffer = byteBuffer buffer = byteBuffer
} }
/// Initializes the message by copying the buffer to the message to be sent. public func decode() throws -> Table {
/// from the builder var buf = buffer
/// - Parameter builder: FlatbufferBuilder that has the bytes created in return try getCheckedRoot(byteBuffer: &buf)
/// - 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
@@ -73,3 +75,30 @@ public struct Message<T: FlatBufferTable>: FlatBufferGRPCMessage {
} }
} }
} }
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public struct FlatBuffersMessageSerializer<
Message: GRPCVerifiableMessage
>: Sendable {
public init() {}
public func serialize<Data>(
message: Message,
_ completion: (UnsafeRawBufferPointer) throws -> Data) throws -> Data
{
return try message.withUnsafeReadableBytes {
try completion($0)
}
}
}
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
public struct FlatBuffersMessageDeserializer<
Message: GRPCVerifiableMessage
>: Sendable {
public init() {}
public func deserialize(pointer: UnsafeRawBufferPointer) throws -> Message {
Message.init(pointer: pointer)
}
}

View File

@@ -115,7 +115,7 @@ public struct TableVerifier {
unionKeyName: String, unionKeyName: String,
fieldName: String, fieldName: String,
required: Bool, required: Bool,
completion: @escaping (inout Verifier, T, Int) throws -> Void) throws completion: (inout Verifier, T, Int) throws -> Void) throws
where T: UnionEnum where T: UnionEnum
{ {
let keyPos = try dereference(key) let keyPos = try dereference(key)

View File

@@ -68,7 +68,7 @@ public struct FlatbufferVector<
} }
extension FlatbufferVector: Encodable where Element: Encodable { extension FlatbufferVector: Encodable where Element: Encodable {
public func encode(to encoder: Encoder) throws { public func encode(to encoder: any Encoder) throws {
var container = encoder.unkeyedContainer() var container = encoder.unkeyedContainer()
for element in self { for element in self {
try container.encode(element) try container.encode(element)

View File

@@ -49,8 +49,8 @@ public struct UnionFlatbufferVector {
public subscript( public subscript(
position: Int, position: Int,
Type: FlatbuffersVectorInitializable Type: any FlatbuffersVectorInitializable
.Type) -> FlatbuffersVectorInitializable .Type) -> any FlatbuffersVectorInitializable
{ {
guard position < count else { guard position < count else {
fatalError( fatalError(

View File

@@ -56,8 +56,15 @@ 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: intLen) try verifier.rangeInBuffer(position: start, size: byteCount.partialValue)
return (start, intLen) return (start, intLen)
} }
} }

View File

@@ -146,7 +146,7 @@ struct _InternalByteBuffer {
#if !os(WASI) #if !os(WASI)
@inline(__always) @inline(__always)
@usableFromInline @usableFromInline
mutating func push(bytes: ContiguousBytes) { mutating func push(bytes: any ContiguousBytes) {
bytes.withUnsafeBytes { ptr in bytes.withUnsafeBytes { ptr in
ensureSpace(size: ptr.count) ensureSpace(size: ptr.count)
memcpy( memcpy(

View File

@@ -30,7 +30,7 @@ public struct ByteBuffer {
enum Blob { enum Blob {
#if !os(WASI) #if !os(WASI)
case data(Data) case data(Data)
case bytes(ContiguousBytes) case bytes(any ContiguousBytes)
#endif #endif
case byteBuffer(_InternalByteBuffer) case byteBuffer(_InternalByteBuffer)

View File

@@ -16,7 +16,7 @@
import Foundation import Foundation
public enum FlexBufferType: UInt64 { public enum FlexBufferType: UInt64, Sendable {
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

View File

@@ -17,7 +17,7 @@
import Foundation import Foundation
@usableFromInline @usableFromInline
enum BitWidth: UInt64, CaseIterable { enum BitWidth: UInt64, CaseIterable, Sendable {
case w8 = 0 case w8 = 0
case w16 = 1 case w16 = 1
case w32 = 2 case w32 = 2

View File

@@ -20,10 +20,10 @@ import Foundation
import Common import Common
#endif #endif
public struct Value: Equatable { public struct Value: Equatable, Sendable {
@usableFromInline @usableFromInline
enum Union: Equatable { enum Union: Equatable, Sendable {
case i(Int64) case i(Int64)
case u(UInt64) case u(UInt64)
case f(Double) case f(Double)

View File

@@ -977,6 +977,9 @@ 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,

View File

@@ -1,5 +1,6 @@
#include "flexbuffers_test.h" #include "flexbuffers_test.h"
#include <memory>
#include <limits> #include <limits>
#include "flatbuffers/flexbuffers.h" #include "flatbuffers/flexbuffers.h"
@@ -13,6 +14,13 @@ 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);
@@ -29,7 +37,10 @@ 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};
slb.Blob(blob, 1); uint32_t aligned_blob[] = {88, 99};
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);
}); });
@@ -62,7 +73,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(), 6); TEST_EQ(vec.size(), 7);
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.
@@ -80,9 +91,15 @@ 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].IsBool(), true); // Check if type is a bool TEST_EQ(vec[4].IsBlob(), true);
TEST_EQ(vec[4].AsBool(), false); // Check if value is false auto aligned_blob = vec[4].AsBlob();
TEST_EQ(vec[5].AsDouble(), 4.0); // This is shared with vec[2] ! TEST_EQ(aligned_blob.size(), 8);
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);
@@ -107,9 +124,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[4].AsBool(), false); // Is false before change TEST_EQ(vec[5].AsBool(), false); // Is false before change
TEST_EQ(vec[4].MutateBool(true), true); // Can change a bool TEST_EQ(vec[5].MutateBool(true), true); // Can change a bool
TEST_EQ(vec[4].AsBool(), true); // Changed bool is now true TEST_EQ(vec[5].AsBool(), true); // Changed bool is now true
// Parse from JSON: // Parse from JSON:
flatbuffers::Parser parser; flatbuffers::Parser parser;

View File

@@ -248,6 +248,93 @@ 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());

View File

@@ -10,6 +10,7 @@ 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);

View File

@@ -3448,4 +3448,250 @@ 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);
}
}
} }

View File

@@ -14,51 +14,58 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Foundation
import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class ByteBufferTests: XCTestCase { struct ByteBufferTests {
@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
XCTAssertNotEqual(memory.baseAddress, ptr) #expect(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
XCTAssertEqual(memory.baseAddress!, ptr) #expect(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
XCTAssertEqual(memory.baseAddress!, ptr.baseAddress!) #expect(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
XCTAssertEqual(memory.baseAddress, ptr.baseAddress) #expect(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)
@@ -69,15 +76,16 @@ final class ByteBufferTests: XCTestCase {
} }
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
XCTAssertEqual(ptr.count, count) #expect(ptr.count == count)
bytes.withUnsafeBufferPointer { bytes.withUnsafeBufferPointer {
XCTAssertEqual( #expect(
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(
@@ -111,11 +119,11 @@ final class ByteBufferTests: XCTestCase {
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
XCTAssertEqual(bufferPointer.count, count) #expect(bufferPointer.count == count)
bytes.withUnsafeBufferPointer { ptr in bytes.withUnsafeBufferPointer { ptr in
XCTAssertEqual( #expect(
UnsafeRawPointer(ptr.baseAddress), UnsafeRawPointer(ptr.baseAddress) ==
UnsafeRawPointer(bufferPointer.baseAddress)) UnsafeRawPointer(bufferPointer.baseAddress))
} }
} }
} }
@@ -126,7 +134,3 @@ 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]
}

View File

@@ -16,18 +16,22 @@
#if compiler(>=6.2) #if compiler(>=6.2)
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) struct FlatBuffersArraysTests {
final class FlatBuffersArraysTests: XCTestCase {
@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)
@Test
func testStructSizes() { func testStructSizes() {
XCTAssertEqual(MemoryLayout<MyGame_Example_NestedStruct>.size, 32) #expect(MemoryLayout<MyGame_Example_NestedStruct>.size == 32)
XCTAssertEqual(MemoryLayout<MyGame_Example_ArrayStruct>.size, 160) #expect(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] = [
@@ -44,9 +48,11 @@ final class FlatBuffersArraysTests: XCTestCase {
] ]
// swiftformat:enable all // swiftformat:enable all
XCTAssertEqual(data, createArrayTable()) #expect(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(
@@ -57,6 +63,8 @@ final class FlatBuffersArraysTests: XCTestCase {
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(
@@ -65,105 +73,110 @@ final class FlatBuffersArraysTests: XCTestCase {
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() {
XCTAssertEqual( #expect(
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!
XCTAssertEqual(a.a, 12.34) #expect(a.a == 12.34)
XCTAssertEqual(a.b.count, 15) #expect(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]
} }
XCTAssertEqual(sum, 120) #expect(sum == 120)
XCTAssertEqual(a.c, -127) #expect(a.c == -127)
XCTAssertEqual(a.d.count, 2) #expect(a.d.count == 2)
let nestedStruct1 = a.d[0] let nestedStruct1 = a.d[0]
XCTAssertEqual(nestedStruct1.a.toArray(), [-1, 2]) #expect(nestedStruct1.a.toArray() == [-1, 2])
XCTAssertEqual(nestedStruct1.b, .a) #expect(nestedStruct1.b == .a)
XCTAssertEqual(nestedStruct1.c.toArray(), [.c, .b]) #expect(nestedStruct1.c.toArray() == [.c, .b])
XCTAssertEqual( #expect(
nestedStruct1.d.toArray(), nestedStruct1.d.toArray() ==
[0x1122334455667788, -0x1122334455667788]) [0x1122334455667788, -0x1122334455667788])
let nestedStruct2 = a.d[1] let nestedStruct2 = a.d[1]
XCTAssertEqual(nestedStruct2.a.toArray(), [3, -4]) #expect(nestedStruct2.a.toArray() == [3, -4])
XCTAssertEqual(nestedStruct2.b, .b) #expect(nestedStruct2.b == .b)
XCTAssertEqual(nestedStruct2.c.toArray(), [.b, .a]) #expect(nestedStruct2.c.toArray() == [.b, .a])
XCTAssertEqual( #expect(
nestedStruct2.d.toArray(), nestedStruct2.d.toArray() ==
[-0x1122334455667788, 0x1122334455667788]) [-0x1122334455667788, 0x1122334455667788])
XCTAssertEqual(a.e, 1) #expect(a.e == 1)
XCTAssertEqual(a.f.count, 2) #expect(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!
XCTAssertEqual(a.a, 12.34) #expect(a.a == 12.34)
XCTAssertEqual(a.b.count, 15) #expect(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]
} }
XCTAssertEqual(sum, 120) #expect(sum == 120)
XCTAssertEqual(a.c, -127) #expect(a.c == -127)
XCTAssertEqual(a.d.count, 2) #expect(a.d.count == 2)
let nestedStruct1 = a.d[0] let nestedStruct1 = a.d[0]
XCTAssertEqual(nestedStruct1.a.reduce(0) { $0 + $1 }, 1) #expect(nestedStruct1.a.reduce(0) { $0 + $1 } == 1)
XCTAssertEqual(nestedStruct1.b, .a) #expect(nestedStruct1.b == .a)
XCTAssertEqual(nestedStruct1.c[0], .c) #expect(nestedStruct1.c[0] == .c)
XCTAssertEqual(nestedStruct1.c[1], .b) #expect(nestedStruct1.c[1] == .b)
let nestedStruct2 = a.d[1] let nestedStruct2 = a.d[1]
XCTAssertEqual(nestedStruct2.a.reduce(0) { $0 + $1 }, -1) #expect(nestedStruct2.a.reduce(0) { $0 + $1 } == -1)
XCTAssertEqual(nestedStruct2.b, .b) #expect(nestedStruct2.b == .b)
XCTAssertEqual(nestedStruct2.c[0], .b) #expect(nestedStruct2.c[0] == .b)
XCTAssertEqual(nestedStruct2.c[1], .a) #expect(nestedStruct2.c[1] == .a)
XCTAssertEqual(nestedStruct2.d[0], -0x1122334455667788) #expect(nestedStruct2.d[0] == -0x1122334455667788)
XCTAssertEqual(nestedStruct2.d[1], 0x1122334455667788) #expect(nestedStruct2.d[1] == 0x1122334455667788)
XCTAssertTrue(a.mutate(b: 1000, at: 0)) #expect(a.mutate(b: 1000, at: 0) == true)
XCTAssertTrue(a.mutate(b: 2000, at: 1)) #expect(a.mutate(b: 2000, at: 1) == true)
XCTAssertTrue(nestedStruct2.mutate(c: .a, at: 0)) #expect(nestedStruct2.mutate(c: .a, at: 0) == true)
XCTAssertTrue(nestedStruct2.mutate(c: .b, at: 1)) #expect(nestedStruct2.mutate(c: .b, at: 1) == true)
XCTAssertEqual(nestedStruct2.c[0], .a) #expect(nestedStruct2.c[0] == .a)
XCTAssertEqual(nestedStruct2.c[1], .b) #expect(nestedStruct2.c[1] == .b)
XCTAssertTrue(nestedStruct2.mutate(d: 0, at: 0)) #expect(nestedStruct2.mutate(d: 0, at: 0) == true)
XCTAssertTrue(nestedStruct2.mutate(d: 0, at: 1)) #expect(nestedStruct2.mutate(d: 0, at: 1) == true)
XCTAssertEqual(nestedStruct2.d.reduce(0) { $0 + $1 }, 0) #expect(nestedStruct2.d.reduce(0) { $0 + $1 } == 0)
let nativeStruct = table.a?.d[1] let nativeStruct = table.a?.d[1]
XCTAssertEqual(nativeStruct?.c[0], .a) #expect(nativeStruct?.c[0] == .a)
XCTAssertEqual(nativeStruct?.c[1], .b) #expect(nativeStruct?.c[1] == .b)
XCTAssertEqual(nativeStruct?.d[0], 0) #expect(nativeStruct?.d[0] == 0)
XCTAssertEqual(nativeStruct?.d[1], 0) #expect(nativeStruct?.d[1] == 0)
XCTAssertTrue(a.mutate(b: 1, at: 0)) #expect(a.mutate(b: 1, at: 0) == true)
XCTAssertTrue(a.mutate(b: 2, at: 1)) #expect(a.mutate(b: 2, at: 1) == true)
XCTAssertTrue(nestedStruct2.mutate(c: .b, at: 0)) #expect(nestedStruct2.mutate(c: .b, at: 0) == true)
XCTAssertTrue(nestedStruct2.mutate(c: .a, at: 1)) #expect(nestedStruct2.mutate(c: .a, at: 1) == true)
XCTAssertTrue(nestedStruct2.mutate(d: -0x1122334455667788, at: 0)) #expect(nestedStruct2.mutate(d: -0x1122334455667788, at: 0) == true)
XCTAssertTrue(nestedStruct2.mutate(d: 0x1122334455667788, at: 1)) #expect(nestedStruct2.mutate(d: 0x1122334455667788, at: 1) == true)
} }
@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)
@@ -233,4 +246,3 @@ extension InlineArray: @retroactive Equatable where Element: Equatable {
} }
#endif #endif

View File

@@ -15,7 +15,7 @@
*/ */
import Foundation import Foundation
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
@@ -24,8 +24,9 @@ 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
class FlatBuffersMonsterWriterTests: XCTestCase { struct FlatBuffersMonsterWriterTests {
@Test
func testData() { func testData() {
// swiftformat:disable all // swiftformat:disable all
let data = Data([ let data = Data([
@@ -47,12 +48,13 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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: #file) let filePath = URL(filePath: #filePath)
.deletingLastPathComponent() .deletingLastPathComponent()
return filePath.absoluteString return filePath.absoluteString
#else #else
@@ -71,6 +73,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
@@ -80,30 +83,32 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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()
XCTAssertEqual(builder.capacity, 1) #expect(builder.capacity == 1)
XCTAssertEqual(builder.size, 0) #expect(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)
XCTAssertEqual(_buffer.capacity, 304) #expect(_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)
XCTAssertEqual(builder.capacity, 512) #expect(builder.capacity == 512)
XCTAssertEqual(builder.size, 0) #expect(builder.size == 0)
} }
@Test
func testCreateMonster() { func testCreateMonster() {
let bytes = createMonster(withPrefix: false) let bytes = createMonster(withPrefix: false)
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -127,11 +132,12 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -150,11 +156,12 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -175,6 +182,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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")
@@ -184,10 +192,11 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
XCTAssertNil(newMonster.pos) #expect(newMonster.pos == nil)
XCTAssertEqual(newMonster.name, "Frodo") #expect(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")
@@ -207,10 +216,11 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
XCTAssertEqual(newMonster.pos!.x, 10) #expect(newMonster.pos!.x == 10)
XCTAssertEqual(newMonster.name, "Barney") #expect(newMonster.name == "Barney")
} }
@Test
func testReadMonsterFromUnsafePointerWithoutCopying() { func testReadMonsterFromUnsafePointerWithoutCopying() {
// swiftformat:disable all // swiftformat:disable all
var array: [UInt8] = [ var array: [UInt8] = [
@@ -242,6 +252,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
@@ -257,37 +268,41 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
let monster: Monster = getRoot(byteBuffer: &buffer) let monster: Monster = getRoot(byteBuffer: &buffer)
let values = monster.testarrayofbools let values = monster.testarrayofbools
XCTAssertEqual(boolArray.count, values.count) #expect(boolArray.count == values.count)
for (index, bool) in monster.testarrayofbools.enumerated() { for (index, bool) in monster.testarrayofbools.enumerated() {
XCTAssertEqual(bool, boolArray[index]) #expect(bool == boolArray[index])
} }
} }
func readVerifiedMonster(fb: ByteBuffer) { func readVerifiedMonster(fb: ByteBuffer) {
var byteBuffer = fb var byteBuffer = fb
XCTAssertNoThrow( do {
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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
XCTAssertEqual(testAligned(), true) #expect(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 {
XCTFail("Base pointer is not defined") Issue.record("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -296,13 +311,14 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
assumingMemoryBound: unlignedPtr, assumingMemoryBound: unlignedPtr,
capacity: ptr.count - 1) capacity: ptr.count - 1)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
XCTAssertEqual(testUnaligned(), true) #expect(testUnaligned() == true)
} }
@Test
func testReadingRemovedSizeUnalignedBuffer() { func testReadingRemovedSizeUnalignedBuffer() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: true) let fbb = createMonster(withPrefix: true)
@@ -311,7 +327,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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 {
XCTFail("Base pointer is not defined") Issue.record("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -321,32 +337,34 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
XCTAssertEqual(testUnaligned(), true) #expect(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 = Message<Monster>(byteBuffer: byteBuffer) let firstMessage = GRPCMessage<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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
} }
let secondByteBuffer = fbb.sizedBuffer let secondByteBuffer = fbb.sizedBuffer
let secondMessage = Message<Monster>(byteBuffer: secondByteBuffer) let secondMessage = GRPCMessage<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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
} }
} }
@Test
func testForceRetainedObject() { func testForceRetainedObject() {
let byteBuffer = { let byteBuffer = {
// swiftformat:disable all // swiftformat:disable all
@@ -452,95 +470,95 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var fb = fb var fb = fb
let monster: Monster = getRoot(byteBuffer: &fb) let monster: Monster = getRoot(byteBuffer: &fb)
XCTAssertFalse(monster.mutate(mana: 10)) #expect(monster.mutate(mana: 10) == false)
XCTAssertEqual(monster.testarrayoftables[0].name, "Barney") #expect(monster.testarrayoftables[0].name == "Barney")
XCTAssertEqual(monster.testarrayoftables[1].name, "Frodo") #expect(monster.testarrayoftables[1].name == "Frodo")
XCTAssertEqual(monster.testarrayoftables[2].name, "Wilma") #expect(monster.testarrayoftables[2].name == "Wilma")
// Example of searching for a table by the key // Example of searching for a table by the key
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Frodo")) #expect(monster.testarrayoftablesBy(key: "Frodo") != nil)
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Barney")) #expect(monster.testarrayoftablesBy(key: "Barney") != nil)
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Wilma")) #expect(monster.testarrayoftablesBy(key: "Wilma") != nil)
XCTAssertEqual(monster.testType, .monster) #expect(monster.testType == .monster)
XCTAssertEqual(monster.mutate(inventory: 1, at: 0), true) #expect(monster.mutate(inventory: 1, at: 0) == true)
XCTAssertEqual(monster.mutate(inventory: 2, at: 1), true) #expect(monster.mutate(inventory: 2, at: 1) == true)
XCTAssertEqual(monster.mutate(inventory: 3, at: 2), true) #expect(monster.mutate(inventory: 3, at: 2) == true)
XCTAssertEqual(monster.mutate(inventory: 4, at: 3), true) #expect(monster.mutate(inventory: 4, at: 3) == true)
XCTAssertEqual(monster.mutate(inventory: 5, at: 4), true) #expect(monster.mutate(inventory: 5, at: 4) == true)
for i in 0..<monster.inventory.count { for i in 0..<monster.inventory.count {
XCTAssertEqual(monster.inventory[i], Byte(i + 1)) #expect(monster.inventory[i] == Byte(i + 1))
} }
XCTAssertEqual(monster.mutate(inventory: 0, at: 0), true) #expect(monster.mutate(inventory: 0, at: 0) == true)
XCTAssertEqual(monster.mutate(inventory: 1, at: 1), true) #expect(monster.mutate(inventory: 1, at: 1) == true)
XCTAssertEqual(monster.mutate(inventory: 2, at: 2), true) #expect(monster.mutate(inventory: 2, at: 2) == true)
XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true) #expect(monster.mutate(inventory: 3, at: 3) == true)
XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true) #expect(monster.mutate(inventory: 4, at: 4) == true)
let vec = monster.mutablePos let vec = monster.mutablePos
XCTAssertEqual(vec?.x, 1) #expect(vec?.x == 1)
XCTAssertTrue(vec?.mutate(x: 55.0) ?? false) #expect(vec?.mutate(x: 55.0) == true)
XCTAssertTrue(vec?.mutate(test1: 55) ?? false) #expect(vec?.mutate(test1: 55) == true)
XCTAssertEqual(vec?.x, 55.0) #expect(vec?.x == 55.0)
XCTAssertEqual(vec?.test1, 55.0) #expect(vec?.test1 == 55.0)
XCTAssertTrue(vec?.mutate(x: 1) ?? false) #expect(vec?.mutate(x: 1) == true)
XCTAssertEqual(vec?.x, 1) #expect(vec?.x == 1)
XCTAssertTrue(vec?.mutate(test1: 3) ?? false) #expect(vec?.mutate(test1: 3) == true)
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
let orignalValues = mutableTest4[0].a let orignalValues = mutableTest4[0].a
XCTAssertEqual(mutableTest4[0].mutate(a: 100), true) #expect(mutableTest4[0].mutate(a: 100) == true)
XCTAssertNotEqual(monster.test4[0].a, orignalValues) #expect(monster.test4[0].a != orignalValues)
XCTAssertEqual(monster.test4[0].a, 100) #expect(monster.test4[0].a == 100)
XCTAssertEqual(mutableTest4[0].mutate(a: orignalValues), true) #expect(mutableTest4[0].mutate(a: orignalValues) == true)
} }
func readFlatbufferMonster(monster: inout MyGame_Example_Monster) { func readFlatbufferMonster(monster: inout MyGame_Example_Monster) {
XCTAssertEqual(monster.hp, 80) #expect(monster.hp == 80)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.name, "MyMonster") #expect(monster.name == "MyMonster")
let pos = monster.pos let pos = monster.pos
XCTAssertEqual(pos?.x, 1) #expect(pos?.x == 1)
XCTAssertEqual(pos?.y, 2) #expect(pos?.y == 2)
XCTAssertEqual(pos?.z, 3) #expect(pos?.z == 3)
XCTAssertEqual(pos?.test1, 3) #expect(pos?.test1 == 3)
XCTAssertEqual(pos?.test2, .green) #expect(pos?.test2 == .green)
let test = pos?.test3 let test = pos?.test3
XCTAssertEqual(test?.a, 5) #expect(test?.a == 5)
XCTAssertEqual(test?.b, 6) #expect(test?.b == 6)
XCTAssertEqual(monster.testType, .monster) #expect(monster.testType == .monster)
let monster2 = monster.test(type: Monster.self) let monster2 = monster.test(type: Monster.self)
XCTAssertEqual(monster2?.name, "Fred") #expect(monster2?.name == "Fred")
XCTAssertEqual(monster.mutate(mana: 10), false) #expect(monster.mutate(mana: 10) == false)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.inventory.count, 5) #expect(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
} }
XCTAssertEqual(sum, 10) #expect(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]
} }
XCTAssertEqual(sum, 10) #expect(sum == 10)
} }
XCTAssertEqual(monster.test4.count, 2) #expect(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)
} }
XCTAssertEqual(sum0, 100) #expect(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 }
@@ -556,7 +574,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
pointerSum += Int(bindedMemory[pointee].a) + pointerSum += Int(bindedMemory[pointee].a) +
Int(bindedMemory[pointee].b) Int(bindedMemory[pointee].b)
} }
XCTAssertEqual(pointerSum, 100) #expect(pointerSum == 100)
} }
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
@@ -564,87 +582,84 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
for test0 in mutableTest4 { for test0 in mutableTest4 {
sum2 += Int(test0.a) + Int(test0.b) sum2 += Int(test0.a) + Int(test0.b)
} }
XCTAssertEqual(sum2, 100) #expect(sum2 == 100)
let stringArray = monster.testarrayofstring let stringArray = monster.testarrayofstring
XCTAssertEqual(stringArray.count, 2) #expect(stringArray.count == 2)
XCTAssertEqual(stringArray[0], "test1") #expect(stringArray[0] == "test1")
XCTAssertEqual(stringArray[1], "test2") #expect(stringArray[1] == "test2")
XCTAssertEqual(monster.testbool, true) #expect(monster.testbool == true)
let array = monster.nameSegmentArray let array = monster.nameSegmentArray
XCTAssertEqual(String(bytes: array ?? [], encoding: .utf8), "MyMonster") #expect(String(bytes: array ?? [], encoding: .utf8) == "MyMonster")
if 0 == monster.testarrayofbools.count { if 0 == monster.testarrayofbools.count {
XCTAssertEqual(monster.testarrayofbools.isEmpty, true) #expect(monster.testarrayofbools.isEmpty == true)
} else { } else {
XCTAssertEqual(monster.testarrayofbools.isEmpty, false) #expect(monster.testarrayofbools.isEmpty == false)
} }
} }
func readObjectApi(monster: MyGame_Example_MonsterT) { func readObjectApi(monster: MyGame_Example_MonsterT) {
XCTAssertEqual(monster.hp, 80) #expect(monster.hp == 80)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.name, "MyMonster") #expect(monster.name == "MyMonster")
let pos = monster.pos let pos = monster.pos
XCTAssertEqual(pos?.x, 1) #expect(pos?.x == 1)
XCTAssertEqual(pos?.y, 2) #expect(pos?.y == 2)
XCTAssertEqual(pos?.z, 3) #expect(pos?.z == 3)
XCTAssertEqual(pos?.test1, 3) #expect(pos?.test1 == 3)
XCTAssertEqual(pos?.test2, .green) #expect(pos?.test2 == .green)
let test = pos?.test3 let test = pos?.test3
XCTAssertEqual(test?.a, 5) #expect(test?.a == 5)
XCTAssertEqual(test?.b, 6) #expect(test?.b == 6)
let monster2 = monster.test?.value as? MyGame_Example_MonsterT let monster2 = monster.test?.value as? MyGame_Example_MonsterT
XCTAssertEqual(monster2?.name, "Fred") #expect(monster2?.name == "Fred")
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
monster.mana = 10 monster.mana = 10
XCTAssertEqual(monster.mana, 10) #expect(monster.mana == 10)
monster.mana = 150 monster.mana = 150
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.inventory.count, 5) #expect(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
} }
XCTAssertEqual(sum, 10) #expect(sum == 10)
XCTAssertEqual(monster.test4.count, 2) #expect(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)
} }
XCTAssertEqual(sum0, 100) #expect(sum0 == 100)
XCTAssertEqual(monster.testbool, true) #expect(monster.testbool == true)
} }
func testEncoding() { @Test
func testEncoding() throws {
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
var sizedBuffer = fbb.sizedBuffer var sizedBuffer = fbb.sizedBuffer
do { struct Test: Decodable {
struct Test: Decodable { struct Pos: Decodable {
struct Pos: Decodable { let x, y, z: Int
let x, y, z: Int
}
let hp: Int
let inventory: [UInt8]
let name: String
let pos: Pos
} }
let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer) let hp: Int
let encoder = JSONEncoder() let inventory: [UInt8]
encoder.keyEncodingStrategy = .convertToSnakeCase let name: String
let data = try encoder.encode(reader) let pos: Pos
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 {
@@ -653,6 +668,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
""" """
} }
@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)
@@ -670,7 +686,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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() {
XCTAssertEqual(array[index], value) #expect(array[index] == value)
} }
} }
} }

View File

@@ -14,11 +14,59 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Foundation
import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersNanInfTests: XCTestCase { struct FlatBuffersNanInfTests {
@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()
@@ -31,54 +79,4 @@ final class FlatBuffersNanInfTests: XCTestCase {
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)
}
}
} }

View File

@@ -14,12 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersStructsTests: XCTestCase { struct FlatBuffersStructsTests {
@Test
func testWritingAndMutatingBools() { func testWritingAndMutatingBools() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
let start = TestMutatingBool.startTestMutatingBool(&fbb) let start = TestMutatingBool.startTestMutatingBool(&fbb)
@@ -30,11 +31,11 @@ final class FlatBuffersStructsTests: XCTestCase {
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
XCTAssertEqual(property?.property, false) #expect(property?.property == false)
property?.mutate(property: false) property?.mutate(property: false)
XCTAssertEqual(property?.property, false) #expect(property?.property == false)
property?.mutate(property: true) property?.mutate(property: true)
XCTAssertEqual(property?.property, true) #expect(property?.property == true)
} }
} }

View File

@@ -14,44 +14,49 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Testing
@testable import Common @testable import Common
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersTests: XCTestCase { struct FlatBuffersTests {
let country = "Norway" let country = "Norway"
func testEndian() { XCTAssertEqual(isLitteEndian, true) } @Test
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)
XCTAssertEqual(o.isEmpty, true) #expect(o.isEmpty == true)
XCTAssertEqual(b.isEmpty, false) #expect(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)
XCTAssertEqual(b.create(string: country).o, 12) #expect(b.create(string: country).o == 12)
XCTAssertEqual(b.create(string: helloWorld).o, 32) #expect(b.create(string: helloWorld).o == 32)
b.clear() b.clear()
XCTAssertEqual(b.create(string: helloWorld).o, 20) #expect(b.create(string: helloWorld).o == 20)
XCTAssertEqual(b.create(string: country).o, 32) #expect(b.create(string: country).o == 32)
b.clear() b.clear()
XCTAssertEqual(b.create(string: String(repeating: "a", count: 257)).o, 264) #expect(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)
XCTAssertNoThrow(b.startTable(with: 0)) _ = b.startTable(with: 0)
b.clear() b.clear()
XCTAssertEqual(b.create(string: country).o, 12) #expect(b.create(string: country).o == 12)
XCTAssertEqual(b.startTable(with: 0), 12) #expect(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(
@@ -66,9 +71,10 @@ final class FlatBuffersTests: XCTestCase {
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
XCTAssertEqual(b.sizedByteArray, v) #expect(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(
@@ -83,9 +89,10 @@ final class FlatBuffersTests: XCTestCase {
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
XCTAssertEqual(b.sizedByteArray, v) #expect(b.sizedByteArray == v)
} }
@Test
func testReadCountry() { func testReadCountry() {
// swiftformat:disable all // swiftformat:disable all
let v: [UInt8] = [ let v: [UInt8] = [
@@ -95,18 +102,20 @@ final class FlatBuffersTests: XCTestCase {
// 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)
XCTAssertEqual(c.lan, 100) #expect(c.lan == 100)
XCTAssertEqual(c.log, 200) #expect(c.log == 200)
XCTAssertEqual(c.nameVector, [78, 111, 114, 119, 97, 121]) #expect(c.nameVector == [78, 111, 114, 119, 97, 121])
XCTAssertEqual(c.name, country) #expect(c.name == country)
} }
@Test
func testWriteNullableStrings() { func testWriteNullableStrings() {
var b = FlatBufferBuilder() var b = FlatBufferBuilder()
XCTAssertTrue(b.create(string: nil).isEmpty) #expect(b.create(string: nil).isEmpty)
XCTAssertTrue(b.createShared(string: nil).isEmpty) #expect(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(
@@ -121,16 +130,17 @@ final class FlatBuffersTests: XCTestCase {
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)
XCTAssertEqual(scalarTable.justI8, 80) #expect(scalarTable.justI8 == 80)
XCTAssertNil(scalarTable.maybeI8) #expect(scalarTable.maybeI8 == nil)
XCTAssertEqual(scalarTable.maybeBool, true) #expect(scalarTable.maybeBool == true)
XCTAssertEqual(scalarTable.defaultI8, 42) #expect(scalarTable.defaultI8 == 42)
XCTAssertEqual(scalarTable.justU8, 100) #expect(scalarTable.justU8 == 100)
XCTAssertEqual(scalarTable.maybeU8, 10) #expect(scalarTable.maybeU8 == 10)
XCTAssertEqual(scalarTable.justEnum, .one) #expect(scalarTable.justEnum == .one)
XCTAssertNil(scalarTable.maybeEnum) #expect(scalarTable.maybeEnum == nil)
} }
@Test
func testAlignmentCrash() { func testAlignmentCrash() {
var builder = FlatBufferBuilder(initialSize: 256) var builder = FlatBufferBuilder(initialSize: 256)

View File

@@ -14,12 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Foundation
import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersUnionTests: XCTestCase { struct FlatBuffersUnionTests {
@Test
func testCreateMonstor() { func testCreateMonstor() {
var b = FlatBufferBuilder(initialSize: 20) var b = FlatBufferBuilder(initialSize: 20)
@@ -36,8 +38,8 @@ final class FlatBuffersUnionTests: XCTestCase {
b.finish(offset: root) b.finish(offset: root)
let buffer = b.sizedByteArray let buffer = b.sizedByteArray
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -45,15 +47,16 @@ final class FlatBuffersUnionTests: XCTestCase {
]) ])
// swiftformat:enable all // swiftformat:enable all
let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer)) let monster = LocalMonster.getRootAsMonster(bb: ByteBuffer(bytes: buffer))
XCTAssertEqual(monster.weapon(at: 0)?.dmg, dmg) #expect(monster.weapon(at: 0)?.dmg == dmg)
XCTAssertEqual(monster.weapon(at: 0)?.name, str) #expect(monster.weapon(at: 0)?.name == str)
XCTAssertEqual(monster.weapon(at: 0)?.nameVector, [65, 120, 101]) #expect(monster.weapon(at: 0)?.nameVector == [65, 120, 101])
let p: Weapon? = monster.equiped() let p: Weapon? = monster.equiped()
XCTAssertEqual(p?.dmg, dmg) #expect(p?.dmg == dmg)
XCTAssertEqual(p?.name, str) #expect(p?.name == str)
XCTAssertEqual(p?.nameVector, [65, 120, 101]) #expect(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")
@@ -84,8 +87,8 @@ final class FlatBuffersUnionTests: XCTestCase {
path: path) path: path)
builder.finish(offset: orc) builder.finish(offset: orc)
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -99,6 +102,7 @@ final class FlatBuffersUnionTests: XCTestCase {
// swiftformat:enable all // swiftformat:enable all
} }
@Test
func testEnumVector() { func testEnumVector() {
let vectorOfEnums: [ColorsNameSpace.RGB] = [.blue, .green] let vectorOfEnums: [ColorsNameSpace.RGB] = [.blue, .green]
@@ -109,8 +113,8 @@ final class FlatBuffersUnionTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -118,12 +122,13 @@ final class FlatBuffersUnionTests: XCTestCase {
// swiftformat:enable all // swiftformat:enable all
let monster = ColorsNameSpace.Monster let monster = ColorsNameSpace.Monster
.getRootAsMonster(bb: builder.sizedBuffer) .getRootAsMonster(bb: builder.sizedBuffer)
XCTAssertEqual(monster.colorsCount, 2) #expect(monster.colorsCount == 2)
let colors = monster.colors let colors = monster.colors
XCTAssertEqual(colors[0], .blue) #expect(colors[0] == .blue)
XCTAssertEqual(colors[1], .green) #expect(colors[1] == .green)
} }
@Test
func testUnionVector() { func testUnionVector() {
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -149,30 +154,30 @@ final class FlatBuffersUnionTests: XCTestCase {
var buffer = fb.sizedBuffer var buffer = fb.sizedBuffer
let movie: Movie = getRoot(byteBuffer: &buffer) let movie: Movie = getRoot(byteBuffer: &buffer)
XCTAssertEqual(movie.charactersType.count, characterType.count) #expect(movie.charactersType.count == characterType.count)
XCTAssertEqual(movie.characters.count, characters.count) #expect(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() {
XCTAssertEqual(element, characterType[index]) #expect(element == characterType[index])
} }
XCTAssertEqual( #expect(
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead ==
7) 7)
XCTAssertEqual( #expect(
movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage ==
swordDmg) swordDmg)
XCTAssertEqual( #expect(
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()
XCTAssertEqual( #expect(
movie.charactersType.count, objc?.characters.count ?? 0) movie.charactersType.count == objc?.characters.count ?? 0)
XCTAssertEqual( #expect(
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)
@@ -180,17 +185,18 @@ final class FlatBuffersUnionTests: XCTestCase {
var _buffer = fb.sizedBuffer var _buffer = fb.sizedBuffer
let packedMovie: Movie = getRoot(byteBuffer: &_buffer) let packedMovie: Movie = getRoot(byteBuffer: &_buffer)
XCTAssertEqual( #expect(
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)
XCTAssertEqual( #expect(
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)
XCTAssertEqual( #expect(
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()
@@ -214,30 +220,31 @@ final class FlatBuffersUnionTests: XCTestCase {
var buffer = fb.sizedBuffer var buffer = fb.sizedBuffer
let movie: Movie = getRoot(byteBuffer: &buffer) let movie: Movie = getRoot(byteBuffer: &buffer)
XCTAssertEqual(movie.mainCharacter(type: String.self), string) #expect(movie.mainCharacter(type: String.self) == string)
XCTAssertEqual( #expect(
movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, movie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead ==
7) 7)
XCTAssertEqual(movie.characters(at: 1, type: String.self), string) #expect(movie.characters(at: 1, type: String.self) == string)
var objc: MovieT? = movie.unpack() var objc: MovieT? = movie.unpack()
XCTAssertEqual(objc?.mainCharacter?.value as? String, string) #expect(objc?.mainCharacter?.value as? String == string)
XCTAssertEqual((objc?.characters[0]?.value as? BookReader)?.booksRead, 7) #expect((objc?.characters[0]?.value as? BookReader)?.booksRead == 7)
XCTAssertEqual(objc?.characters[1]?.value as? String, string) #expect(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)
XCTAssertEqual(packedMovie.mainCharacter(type: String.self), string) #expect(packedMovie.mainCharacter(type: String.self) == string)
XCTAssertEqual( #expect(
packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead, packedMovie.characters(at: 0, type: BookReader_Mutable.self)?.booksRead ==
7) 7)
XCTAssertEqual(packedMovie.characters(at: 1, type: String.self), string) #expect(packedMovie.characters(at: 1, type: String.self) == string)
} }
func testEncoding() { @Test
func testEncoding() throws {
let string = "Awesome \\\\t\t\nstring!" let string = "Awesome \\\\t\t\nstring!"
var fb = FlatBufferBuilder() var fb = FlatBufferBuilder()
@@ -265,16 +272,12 @@ final class FlatBuffersUnionTests: XCTestCase {
Movie.finish(&fb, end: end) Movie.finish(&fb, end: end)
var sizedBuffer = fb.sizedBuffer var sizedBuffer = fb.sizedBuffer
do { let reader: Movie = try getCheckedRoot(byteBuffer: &sizedBuffer)
let reader: Movie = try getCheckedRoot(byteBuffer: &sizedBuffer) let encoder = JSONEncoder()
let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.keyEncodingStrategy = .convertToSnakeCase encoder.outputFormatting = [.sortedKeys]
encoder.outputFormatting = [.sortedKeys] let data = try encoder.encode(reader)
let data = try encoder.encode(reader) #expect(String(data: data, encoding: .utf8) == jsonData)
XCTAssertEqual(String(data: data, encoding: .utf8), jsonData)
} catch {
XCTFail(error.localizedDescription)
}
} }
var jsonData: String { var jsonData: String {

View File

@@ -14,12 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersVectors: XCTestCase { struct FlatBuffersVectors {
@Test
func testCreatingTwoCountries() { func testCreatingTwoCountries() {
let norway = "Norway" let norway = "Norway"
let denmark = "Denmark" let denmark = "Denmark"
@@ -40,8 +41,8 @@ final class FlatBuffersVectors: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -51,18 +52,20 @@ final class FlatBuffersVectors: XCTestCase {
// 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
XCTAssertEqual( #expect(
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
@@ -76,8 +79,8 @@ final class FlatBuffersVectors: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -85,28 +88,31 @@ final class FlatBuffersVectors: XCTestCase {
// 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)
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 0, 0, 0, 0]) #expect(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
XCTAssertEqual( #expect(
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"
@@ -119,8 +125,8 @@ final class FlatBuffersVectors: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -128,6 +134,7 @@ final class FlatBuffersVectors: XCTestCase {
// 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)
@@ -136,10 +143,11 @@ final class FlatBuffersVectors: XCTestCase {
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() {
XCTAssertEqual(num, data[index]) #expect(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)
@@ -148,10 +156,11 @@ final class FlatBuffersVectors: XCTestCase {
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() {
XCTAssertEqual(num, data[index]) #expect(num == data[index])
} }
} }
@Test
func testHasForArray() { func testHasForArray() {
var builder = FlatBufferBuilder(initialSize: 20) var builder = FlatBufferBuilder(initialSize: 20)
let emptyVector = [UInt8]() let emptyVector = [UInt8]()
@@ -166,14 +175,14 @@ final class FlatBuffersVectors: XCTestCase {
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)
XCTAssertEqual(msg.none_.isEmpty, true) #expect(msg.none_.isEmpty == true)
XCTAssertEqual(msg.empty.isEmpty, true) #expect(msg.empty.isEmpty == true)
XCTAssertEqual(msg.empty.count, 0) #expect(msg.empty.count == 0)
XCTAssertEqual(msg.array.isEmpty, false) #expect(msg.array.isEmpty == false)
XCTAssertEqual(msg.array.count, 3) #expect(msg.array.count == 3)
for i in msg.array.startIndex..<msg.array.endIndex { for i in msg.array.startIndex..<msg.array.endIndex {
XCTAssertEqual(msg.array[i], 1 + UInt64(i)) #expect(msg.array[i] == 1 + UInt64(i))
} }
let array = msg.withUnsafePointerToArray { ptr, count in let array = msg.withUnsafePointerToArray { ptr, count in
@@ -185,7 +194,7 @@ final class FlatBuffersVectors: XCTestCase {
return Array(ptr) return Array(ptr)
} }
XCTAssertEqual(array, [1, 2, 3]) #expect(array == [1, 2, 3])
} }
} }

View File

@@ -14,14 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatBuffersDoubleTests: XCTestCase { struct FlatBuffersDoubleTests {
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(
@@ -38,9 +39,10 @@ final class FlatBuffersDoubleTests: XCTestCase {
97, 121, 0, 0, 97, 121, 0, 0,
] ]
// swiftformat:enable all // swiftformat:enable all
XCTAssertEqual(b.sizedByteArray, v) #expect(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(
@@ -57,7 +59,7 @@ final class FlatBuffersDoubleTests: XCTestCase {
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
XCTAssertEqual(b.sizedByteArray, v) #expect(b.sizedByteArray == v)
} }
} }

View File

@@ -15,11 +15,11 @@
*/ */
import Foundation import Foundation
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
class FlatBuffersMoreDefaults: XCTestCase { struct FlatBuffersMoreDefaults {
func testFlatbuffersObject() { func testFlatbuffersObject() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
@@ -27,61 +27,58 @@ class FlatBuffersMoreDefaults: XCTestCase {
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)
XCTAssertEqual(defaults.emptyString, "") #expect(defaults.emptyString == "")
XCTAssertEqual(defaults.someString, "some") #expect(defaults.someString == "some")
XCTAssertEqual(defaults.ints.isEmpty, true) #expect(defaults.ints.isEmpty == true)
XCTAssertEqual(defaults.floats.isEmpty, true) #expect(defaults.floats.isEmpty == true)
XCTAssertEqual(defaults.bools.isEmpty, true) #expect(defaults.bools.isEmpty == true)
XCTAssertEqual(defaults.ints.count, 0) #expect(defaults.ints.count == 0)
XCTAssertEqual(defaults.floats.count, 0) #expect(defaults.floats.count == 0)
XCTAssertEqual(defaults.abcs.count, 0) #expect(defaults.abcs.count == 0)
XCTAssertEqual(defaults.bools.count, 0) #expect(defaults.bools.count == 0)
} }
func testFlatbuffersObjectAPI() { func testFlatbuffersObjectAPI() {
var fbb = FlatBufferBuilder() var fbb = FlatBufferBuilder()
let defaults = MoreDefaultsT() let defaults = MoreDefaultsT()
XCTAssertEqual(defaults.emptyString, "") #expect(defaults.emptyString == "")
XCTAssertEqual(defaults.someString, "some") #expect(defaults.someString == "some")
XCTAssertEqual(defaults.ints, []) #expect(defaults.ints == [])
XCTAssertEqual(defaults.floats, []) #expect(defaults.floats == [])
XCTAssertEqual(defaults.abcs, []) #expect(defaults.abcs == [])
XCTAssertEqual(defaults.bools, []) #expect(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)
XCTAssertEqual(fDefaults.emptyString, "") #expect(fDefaults.emptyString == "")
XCTAssertEqual(fDefaults.someString, "some") #expect(fDefaults.someString == "some")
XCTAssertEqual(fDefaults.ints.isEmpty, true) #expect(fDefaults.ints.isEmpty == true)
XCTAssertEqual(fDefaults.floats.isEmpty, true) #expect(fDefaults.floats.isEmpty == true)
XCTAssertEqual(fDefaults.ints.count, 0) #expect(fDefaults.ints.count == 0)
XCTAssertEqual(fDefaults.floats.count, 0) #expect(fDefaults.floats.count == 0)
XCTAssertEqual(fDefaults.abcs.count, 0) #expect(fDefaults.abcs.count == 0)
XCTAssertEqual(fDefaults.bools.count, 0) #expect(fDefaults.bools.count == 0)
} }
func testEncoding() { @Test
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
do { struct Test: Decodable {
struct Test: Decodable { var emptyString: String
var emptyString: String var someString: 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 == "")
} }
} }

View File

@@ -14,25 +14,20 @@
* limitations under the License. * limitations under the License.
*/ */
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
final class FlatbuffersVerifierTests: XCTestCase { final class FlatbuffersVerifierTests {
var buffer: ByteBuffer! private var buffer: ByteBuffer
var validFlatbuffersObject: ByteBuffer! private var validFlatbuffersObject: ByteBuffer
var invalidFlatbuffersObject: ByteBuffer! private var invalidFlatbuffersObject: ByteBuffer
var invalidFlatbuffersObject2: ByteBuffer! private var invalidFlatbuffersObject2: ByteBuffer
var invalidFlatbuffersObject3: ByteBuffer! private var invalidFlatbuffersObject3: ByteBuffer
override func setUp() { init() {
// 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,
@@ -94,186 +89,250 @@ final class FlatbuffersVerifierTests: XCTestCase {
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
} }
func testVeriferInitPassing() { @Test
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)
XCTAssertNoThrow(try Verifier(buffer: &buffer)) _ = 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)
XCTAssertThrowsError(try Verifier(buffer: &buffer)) #expect(throws: FlatbuffersErrors.exceedsMaxSizeAllowed) {
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)
do { #expect(throws: FlatbuffersErrors.bufferDoesntContainID) {
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)
} }
} }
func testVerifierCheckAlignment() { @Test
func testVerifierCheckAlignment() throws {
let verifier = try! Verifier(buffer: &buffer) let verifier = try! Verifier(buffer: &buffer)
do { #expect(throws: FlatbuffersErrors.missAlignedPointer(
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)
XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self)) try newVerifer.isAligned(position: 16, type: Int.self)
} }
func testRangeInBuffer() { @Test
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
XCTAssertNoThrow(try verifier.rangeInBuffer(position: 24, size: size)) try verifier.rangeInBuffer(position: 24, size: size)
XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, 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: 30, size: size)) }
XCTAssertThrowsError(try verifier.rangeInBuffer(position: 32, size: size)) #expect(throws: FlatbuffersErrors.outOfBounds(position: 34, end: 32)) {
XCTAssertThrowsError(try verifier.rangeInBuffer(position: 34, size: size)) try verifier.rangeInBuffer(
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)
} }
} }
func testPositionInBuffer() { @Test
func testPositionInBuffer() throws {
let verifier = try! Verifier(buffer: &buffer) let verifier = try! Verifier(buffer: &buffer)
XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self)) try verifier.inBuffer(position: 0, of: Int64.self)
XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self)) try verifier.inBuffer(position: 24, of: Int64.self)
XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
XCTAssertThrowsError(try verifier.inBuffer(position: 25, of: Int64.self)) #expect(
XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int32.self)) throws: FlatbuffersErrors.missAlignedPointer(
XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int64.self)) position: -9,
XCTAssertThrowsError(try verifier.inBuffer(position: 30, of: Int64.self)) type: "Int64"))
XCTAssertThrowsError(try verifier.inBuffer(position: 32, of: Int64.self)) {
XCTAssertThrowsError(try verifier.inBuffer(position: 34, of: Int64.self)) try verifier.inBuffer(position: -9, 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)
}
} }
func testVisitTable() { @Test
func testVisitTable() throws {
var verifier = try! Verifier(buffer: &validFlatbuffersObject) var verifier = try! Verifier(buffer: &validFlatbuffersObject)
XCTAssertNoThrow(try verifier.visitTable(at: 48)) _ = try verifier.visitTable(at: 48)
verifier.reset() verifier.reset()
} }
func testTableVerifier() { @Test
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)
XCTAssertEqual(verifier.depth, 1) #expect(verifier.depth == 1)
XCTAssertEqual(verifier.tableCount, 1) #expect(verifier.tableCount == 1)
XCTAssertNoThrow( try tableVerifer.visit(
try tableVerifer.visit( field: 4,
field: 4, fieldName: "Vec",
fieldName: "Vec", required: false,
required: false, type: Vec3.self)
type: Vec3.self))
XCTAssertNoThrow(
try tableVerifer.visit(
field: 8,
fieldName: "hp",
required: false,
type: Int16.self))
XCTAssertNoThrow( try tableVerifer.visit(
try tableVerifer.visit( field: 8,
field: 10, fieldName: "hp",
fieldName: "name", required: false,
required: true, type: Int16.self)
type: ForwardOffset<String>.self))
XCTAssertNoThrow( try tableVerifer.visit(
try tableVerifer.visit( field: 10,
field: 14, fieldName: "name",
fieldName: "inventory", required: true,
required: false, type: ForwardOffset<String>.self)
type: ForwardOffset<Vector<UInt8, UInt8>>.self))
XCTAssertNoThrow( try tableVerifer.visit(
try tableVerifer.visit( field: 14,
field: 22, fieldName: "inventory",
fieldName: "test4", required: false,
required: false, type: ForwardOffset<Vector<UInt8, UInt8>>.self)
type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>
.self))
XCTAssertNoThrow( try tableVerifer.visit(
try tableVerifer.visit( field: 22,
field: 24, fieldName: "test4",
fieldName: "Vector of strings", required: false,
required: false, type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>
type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self)) .self)
do { try tableVerifer.visit(
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"))
} }
do { try tableVerifer.visit(
try tableVerifer.visit( unionKey: 18,
unionKey: 18, unionField: 20,
unionField: 20, unionKeyName: "testType",
unionKeyName: "testType", fieldName: "test",
fieldName: "test", required: false,
required: false, completion: { (verifier, key: MyGame_Example_Any_, pos) in
completion: { (verifier, key: MyGame_Example_Any_, pos) in switch key {
switch key { case .none_:
case .none_: break // NOTE - SWIFT doesnt support none
break case .monster:
case .monster: try ForwardOffset<MyGame_Example_Monster>.verify(
try ForwardOffset<MyGame_Example_Monster>.verify( &verifier,
&verifier, at: pos,
at: pos, of: MyGame_Example_Monster.self)
of: MyGame_Example_Monster.self) case .testsimpletablewithenum:
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()
XCTAssertEqual(verifier.depth, 0) #expect(verifier.depth == 0)
} }
func testVerifyUnionVectors() { @Test
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,
@@ -281,10 +340,11 @@ final class FlatbuffersVerifierTests: XCTestCase {
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
XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie) _ = try getCheckedRoot(byteBuffer: &byteBuffer) as Movie
} }
func testErrorWrongFileId() { @Test
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,
@@ -292,12 +352,14 @@ final class FlatbuffersVerifierTests: XCTestCase {
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
XCTAssertThrowsError( #expect(throws: FlatbuffersErrors.bufferIdDidntMatchPassedId) {
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: [
@@ -306,41 +368,71 @@ final class FlatbuffersVerifierTests: XCTestCase {
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
XCTAssertThrowsError( #expect(throws: FlatbuffersErrors.prefixedSizeNotEqualToBufferSize) {
try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie) try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie
}
} }
func testFullVerifier() { @Test
XCTAssertNoThrow( func testFullVerifier() throws {
_ =
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster) byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster
} }
func testFullVerifierWithFileId() { @Test
XCTAssertNoThrow( func testFullVerifierWithFileId() throws {
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() {
XCTAssertThrowsError( #expect(throws: FlatbuffersErrors.self) {
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &invalidFlatbuffersObject) as MyGame_Example_Monster) byteBuffer: &self.invalidFlatbuffersObject) as MyGame_Example_Monster
}
} }
@Test
func testInvalidBuffer2() { func testInvalidBuffer2() {
XCTAssertThrowsError( #expect(throws: FlatbuffersErrors.self) {
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &invalidFlatbuffersObject2) as MyGame_Example_Monster) byteBuffer: &self.invalidFlatbuffersObject2) as MyGame_Example_Monster
}
} }
@Test
func testInvalidBuffer3() { func testInvalidBuffer3() {
XCTAssertThrowsError( #expect(throws: FlatbuffersErrors.self) {
try getCheckedRoot( try getCheckedRoot(
byteBuffer: &invalidFlatbuffersObject3) as MyGame_Example_Monster) byteBuffer: &self.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()
@@ -362,9 +454,14 @@ final class FlatbuffersVerifierTests: XCTestCase {
charactersVectorOffset: characterVector) charactersVectorOffset: characterVector)
Movie.finish(&fb, end: end) Movie.finish(&fb, end: end)
var buf = fb.sizedBuffer var buf = fb.sizedBuffer
XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie) do {
_ = 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")
@@ -383,22 +480,22 @@ final class FlatbuffersVerifierTests: XCTestCase {
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))
XCTAssertEqual(verifier.depth, 1) #expect(verifier.depth == 1)
XCTAssertEqual(verifier.tableCount, 1) #expect(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))
XCTAssertEqual(verifier.depth, 2) #expect(verifier.depth == 2)
XCTAssertEqual(verifier.tableCount, 2) #expect(verifier.tableCount == 2)
nestedTable.finish() nestedTable.finish()
XCTAssertEqual(verifier.depth, 1) #expect(verifier.depth == 1)
XCTAssertEqual(verifier.tableCount, 2) #expect(verifier.tableCount == 2)
tableVerifer.finish() tableVerifer.finish()
XCTAssertEqual(verifier.depth, 0) #expect(verifier.depth == 0)
XCTAssertEqual(verifier.tableCount, 2) #expect(verifier.tableCount == 2)
} }
func add(buffer: inout ByteBuffer, v: Int32, p: Int) { func add(buffer: inout ByteBuffer, v: Int32, p: Int) {

View File

@@ -74,7 +74,7 @@ public struct Property_Mutable: FlatBufferStruct, FlatbuffersVectorInitializable
} }
} }
public struct TestMutatingBool: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct TestMutatingBool: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_ArrayTable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct DataModel_A: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct DataModel_A: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -5,206 +5,568 @@
// swiftlint:disable all // swiftlint:disable all
// swiftformat:disable all // swiftformat:disable all
#if !os(Windows) #if !os(Windows) && compiler(>=6.0)
import Foundation
import GRPC
import NIO
import NIOHTTP1
import FlatBuffers import FlatBuffers
import Foundation
import GRPCCore
import GRPCNIOTransportCore
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 MyGame_Example_MonsterStorageServiceClient, then call methods of this protocol to make API calls. /// Usage: instantiate MyGame.Example.MonsterStorageServiceClient, then call methods of this protocol to make API calls.
public protocol MyGame_Example_MonsterStorageClientProtocol: GRPCClient { @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension FlatBuffersMessageSerializer: MessageSerializer {
var serviceName: String { get } public func serialize<Bytes>(_ message: Message) throws -> Bytes where Bytes : GRPCCore.GRPCContiguousBytes {
do {
var interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol? { get } return try self.serialize(message: message) { GRPCNIOTransportBytes($0) } as! Bytes
} catch let error {
func Store( throw RPCError(
_ request: Message<MyGame_Example_Monster> code: .invalidArgument,
, callOptions: CallOptions? message: "Can't serialize message",
) -> UnaryCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> cause: error
)
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>>
}
extension MyGame_Example_MonsterStorageClientProtocol {
public var serviceName: String { "MyGame.Example.MonsterStorage" }
public func Store(
_ request: Message<MyGame_Example_Monster>
, callOptions: CallOptions? = nil
) -> UnaryCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
return self.makeUnaryCall(
path: "/MyGame.Example.MonsterStorage/Store",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeStoreInterceptors() ?? []
)
}
public func Retrieve(
_ request: Message<MyGame_Example_Stat>
, callOptions: CallOptions? = nil,
handler: @escaping (Message<MyGame_Example_Monster>) -> Void
) -> ServerStreamingCall<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>> {
return self.makeServerStreamingCall(
path: "/MyGame.Example.MonsterStorage/Retrieve",
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeRetrieveInterceptors() ?? [],
handler: handler
)
}
public func GetMaxHitPoint(
callOptions: CallOptions? = nil
) -> ClientStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
return self.makeClientStreamingCall(
path: "/MyGame.Example.MonsterStorage/GetMaxHitPoint",
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetMaxHitPointInterceptors() ?? []
)
}
public func GetMinMaxHitPoints(
callOptions: CallOptions? = nil,
handler: @escaping (Message<MyGame_Example_Stat> ) -> Void
) -> BidirectionalStreamingCall<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>> {
return self.makeBidirectionalStreamingCall(
path: "/MyGame.Example.MonsterStorage/GetMinMaxHitPoints",
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetMinMaxHitPointsInterceptors() ?? [],
handler: handler
)
}
}
public protocol MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol {
/// - Returns: Interceptors to use when invoking 'Store'.
func makeStoreInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
/// - Returns: Interceptors to use when invoking 'Retrieve'.
func makeRetrieveInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>]
/// - Returns: Interceptors to use when invoking 'GetMaxHitPoint'.
func makeGetMaxHitPointInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
/// - Returns: Interceptors to use when invoking 'GetMinMaxHitPoints'.
func makeGetMinMaxHitPointsInterceptors() -> [ClientInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>]
}
public final class MyGame_Example_MonsterStorageServiceClient: MyGame_Example_MonsterStorageClientProtocol {
public let channel: GRPCChannel
public var defaultCallOptions: CallOptions
public var interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol?
public init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: MyGame_Example_MonsterStorageClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
}
}
public protocol MyGame_Example_MonsterStorageProvider: CallHandlerProvider {
var interceptors: MyGame_Example_MonsterStorageServerInterceptorFactoryProtocol? { get }
func Store(request: Message<MyGame_Example_Monster>, context: StatusOnlyCallContext) -> EventLoopFuture<Message<MyGame_Example_Stat>>
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>
func GetMinMaxHitPoints(context: StreamingResponseCallContext<Message<MyGame_Example_Stat>>) -> EventLoopFuture<(StreamEvent<Message<MyGame_Example_Monster>>) -> Void>
}
public extension MyGame_Example_MonsterStorageProvider {
var serviceName: Substring { return "MyGame.Example.MonsterStorage" }
func handle(method name: Substring, context: CallHandlerContext) -> GRPCServerHandlerProtocol? {
switch name {
case "Store":
return UnaryServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Monster>>(),
responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Stat>>(),
interceptors: self.interceptors?.makeStoreInterceptors() ?? [],
userFunction: self.Store(request:context:))
case "Retrieve":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: GRPCPayloadDeserializer<Message<MyGame_Example_Stat>>(),
responseSerializer: GRPCPayloadSerializer<Message<MyGame_Example_Monster>>(),
interceptors: self.interceptors?.makeRetrieveInterceptors() ?? [],
userFunction: self.Retrieve(request:context:))
case "GetMaxHitPoint":
return ClientStreamingServerHandler(
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, *)
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 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, *)
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(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>> {
let response = try await self.Store(
request: GRPCCore.ServerRequest(stream: request),
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,
context: context
)
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(
request: GRPCCore.ServerRequest<GRPCMessage<MyGame_Example_Monster>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>> {
return GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Monster>>(
metadata: [:],
producer: { writer in
try await self.Retrieve(
request: request.message,
response: writer,
context: context
)
return [:]
}
)
}
public func GetMaxHitPoint(
request: GRPCCore.StreamingServerRequest<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.GetMaxHitPoint(
request: request.messages,
context: context
),
metadata: [:]
)
}
public func GetMinMaxHitPoints(
request: GRPCCore.StreamingServerRequest<GRPCMessage<MyGame_Example_Stat>>,
context: GRPCCore.ServerContext
) async throws -> GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>> {
return GRPCCore.StreamingServerResponse<GRPCMessage<MyGame_Example_Stat>>(
metadata: [:],
producer: { writer in
try await self.GetMinMaxHitPoints(
request: request.messages,
response: writer,
context: context
)
return [:]
}
)
}
}
// MARK: MyGame.Example.MonsterStorage Client
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
extension MyGame_Example_MonsterStorage {
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>(
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,
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>(
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.StreamingClientResponse<GRPCMessage<MyGame_Example_Stat>>) 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 MyGame_Example_MonsterStorage {
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 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, *)
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>(
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>(
request: GRPCCore.StreamingClientRequest<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.GetMaxHitPoint(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
options: options,
onResponse: handleResponse
)
}
public func GetMinMaxHitPoints<Result>(
request: GRPCCore.StreamingClientRequest<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.GetMinMaxHitPoints(
request: request,
serializer: FlatBuffersMessageSerializer<GRPCMessage<MyGame_Example_Stat>>(),
deserializer: FlatBuffersMessageDeserializer<GRPCMessage<MyGame_Example_Stat>>(),
options: options,
onResponse: handleResponse
)
}
} }
public protocol MyGame_Example_MonsterStorageServerInterceptorFactoryProtocol { @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
/// - Returns: Interceptors to use when handling 'Store'. extension MyGame_Example_MonsterStorage.ClientProtocol {
/// Defaults to calling `self.makeInterceptors()`. public func Store<Result>(
func makeStoreInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>] _ message: GRPCMessage<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
)
}
/// - Returns: Interceptors to use when handling 'Retrieve'. public func Retrieve<Result>(
/// Defaults to calling `self.makeInterceptors()`. _ message: GRPCMessage<MyGame_Example_Monster>,
func makeRetrieveInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Stat>, Message<MyGame_Example_Monster>>] metadata: GRPCCore.Metadata = [:],
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
)
}
/// - Returns: Interceptors to use when handling 'GetMaxHitPoint'. public func GetMaxHitPoint<Result>(
/// Defaults to calling `self.makeInterceptors()`. metadata: GRPCCore.Metadata = [:],
func makeGetMaxHitPointInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>] options: GRPCCore.CallOptions = .defaults,
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
)
}
/// - Returns: Interceptors to use when handling 'GetMinMaxHitPoints'. public func GetMinMaxHitPoints<Result>(
/// Defaults to calling `self.makeInterceptors()`. metadata: GRPCCore.Metadata = [:],
func makeGetMinMaxHitPointsInterceptors() -> [ServerInterceptor<Message<MyGame_Example_Monster>, Message<MyGame_Example_Stat>>] options: GRPCCore.CallOptions = .defaults,
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

View File

@@ -662,7 +662,7 @@ public struct MyGame_Example_StructOfStructsOfStructs_Mutable: FlatBufferStruct,
} }
} }
public struct MyGame_InParentNamespace: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_InParentNamespace: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example2_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Stat: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Referrable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_TypeAliases: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -31,7 +31,7 @@ extension ABC: Encodable {
} }
} }
public struct MoreDefaults: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MoreDefaults: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct Swift_Tests_NanInfTable: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable { public struct Swift_Tests_NanInfTable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable {
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 }

View File

@@ -31,7 +31,7 @@ extension optional_scalars_OptionalByte: Encodable {
} }
} }
public struct optional_scalars_ScalarStuff: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable { public struct optional_scalars_ScalarStuff: FlatBufferVerifiableTable, FlatbuffersVectorInitializable {
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 }

View File

@@ -320,7 +320,7 @@ public struct FallingTub_Mutable: FlatBufferStruct, FlatbuffersVectorInitializab
} }
} }
public struct Attacker: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct Attacker: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct HandFan: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct Movie: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -8,7 +8,7 @@ import Common
import FlatBuffers import FlatBuffers
public struct Swift_Tests_Vectors: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable { public struct Swift_Tests_Vectors: FlatBufferVerifiableTable, FlatbuffersVectorInitializable {
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 }

View File

@@ -16,17 +16,19 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Foundation
import Testing
final class FlexBuffersJSONTests: XCTestCase { struct FlexBuffersJSONTests {
@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
XCTAssertEqual( #expect(
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
@@ -37,15 +39,15 @@ final class FlexBuffersJSONTests: XCTestCase {
with: data, with: data,
options: []) as! [String: Any] options: []) as! [String: Any]
XCTAssertEqual(decodedData["bar"] as! [Int], [1, 2, 3]) #expect(decodedData["bar"] as! [Int] == [1, 2, 3])
XCTAssertEqual(decodedData["bar3"] as! [Int], [1, 2, 3]) #expect(decodedData["bar3"] as! [Int] == [1, 2, 3])
let vec: [Any] = decodedData["vec"] as! [Any] let vec: [Any] = decodedData["vec"] as! [Any]
XCTAssertEqual(vec[0] as! Int, -100) #expect(vec[0] as! Int == -100)
XCTAssertEqual(vec[1] as! String, "Fred") #expect(vec[1] as! String == "Fred")
XCTAssertEqual(vec[2] as! Double, 4.0) #expect(vec[2] as! Double == 4.0)
XCTAssertEqual(vec[3] as! String, "M") #expect(vec[3] as! String == "M")
XCTAssertEqual(vec[4] as! Bool, false) #expect(vec[4] as! Bool == false)
XCTAssertEqual(vec[5] as! Double, 4.0) #expect(vec[5] as! Double == 4.0)
} }
} }

View File

@@ -15,22 +15,26 @@
*/ */
import Common import Common
import XCTest import Foundation
import Testing
@testable import FlexBuffers @testable import FlexBuffers
final class FlexBuffersReaderTests: XCTestCase { struct FlexBuffersReaderTests {
@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,
@@ -38,87 +42,87 @@ final class FlexBuffersReaderTests: XCTestCase {
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(data: fbx.data)) try validate(buffer: ByteBuffer(data: fbx.data))
XCTAssertEqual(fbx.capacity, 512) #expect(fbx.capacity == 512)
fbx.reset() fbx.reset()
XCTAssertEqual(fbx.writerIndex, 0) #expect(fbx.writerIndex == 0)
XCTAssertEqual(fbx.capacity, 8) #expect(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)
XCTAssertEqual(fbx.writerIndex, 0) #expect(fbx.writerIndex == 0)
XCTAssertEqual(fbx.capacity, 512) #expect(fbx.capacity == 512)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(data: fbx.data)) try validate(buffer: ByteBuffer(data: fbx.data))
XCTAssertEqual(fbx.capacity, 512) #expect(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)!
XCTAssertEqual(reference.type, .map) #expect(reference.type == .map)
let map = reference.map! let map = reference.map!
XCTAssertEqual(map.count, 7) #expect(map.count == 7)
let vecRef = map["vec"]! let vecRef = map["vec"]!
XCTAssertEqual(vecRef.type, .vector) #expect(vecRef.type == .vector)
let vec = vecRef.vector! let vec = vecRef.vector!
XCTAssertEqual(vec.count, 6) #expect(vec.count == 6)
XCTAssertEqual(vec[0]?.type, .int) #expect(vec[0]?.type == .int)
XCTAssertEqual(vec[0]?.int, -100) #expect(vec[0]?.int == -100)
XCTAssertEqual(vec[1]?.type, .string) #expect(vec[1]?.type == .string)
XCTAssertEqual(vec[1]?.cString, "Fred") #expect(vec[1]?.cString == "Fred")
XCTAssertNil(vec[1]?.int) #expect(vec[1]?.int == nil)
XCTAssertEqual(vec[2]?.double, 4.0) #expect(vec[2]?.double == 4.0)
XCTAssertTrue(vec[3]?.type == .blob) #expect(vec[3]?.type == .blob)
let blob = vec[3]!.blob { pointer in let blob = vec[3]!.blob { pointer in
Array(pointer) Array(pointer)
} }
XCTAssertEqual(blob?.count, 1) #expect(blob?.count == 1)
XCTAssertEqual(blob?[0], 77) #expect(blob?[0] == 77)
XCTAssertEqual(vec[4]?.type, .bool) #expect(vec[4]?.type == .bool)
XCTAssertEqual(vec[4]?.bool, false) #expect(vec[4]?.bool == false)
XCTAssertEqual(vec[5]?.double, 4.0) // Shared with vec[2] #expect(vec[5]?.double == 4.0) // Shared with vec[2]
let barVec = map["bar"]!.typedVector! let barVec = map["bar"]!.typedVector!
XCTAssertEqual(barVec.count, 3) #expect(barVec.count == 3)
XCTAssertEqual(barVec[2]?.int, 3) #expect(barVec[2]?.int == 3)
XCTAssertEqual(barVec[2]?.asInt(), UInt8(3)) #expect(barVec[2]?.asInt() == UInt8(3))
let fixedVec = map["bar3"]!.fixedTypedVector! let fixedVec = map["bar3"]!.fixedTypedVector!
XCTAssertEqual(fixedVec.count, 3) #expect(fixedVec.count == 3)
XCTAssertEqual(fixedVec[2]?.int, 3) #expect(fixedVec[2]?.int == 3)
XCTAssertEqual(fixedVec[2]?.asInt(), UInt8(3)) #expect(fixedVec[2]?.asInt() == UInt8(3))
XCTAssertEqual(map["bool"]?.bool, true) #expect(map["bool"]?.bool == true)
let boolsVector = map["bools"]!.typedVector! let boolsVector = map["bools"]!.typedVector!
XCTAssertEqual(boolsVector.type, .bool) #expect(boolsVector.type == .bool)
XCTAssertEqual(boolsVector[0]?.bool, true) #expect(boolsVector[0]?.bool == true)
XCTAssertEqual(boolsVector[1]?.bool, false) #expect(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 {
XCTAssertEqual(buff.load(fromByteOffset: i, as: Bool.self), bools[i]) #expect(buff.load(fromByteOffset: i, as: Bool.self) == bools[i])
} }
} }
XCTAssertEqual(map["foo"]?.double, 100) #expect(map["foo"]?.double == 100)
XCTAssertNil(map["unknown"]) #expect(map["unknown"] == nil)
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
XCTAssertEqual(mymap?.keys[0]?.cString, map.keys[4]?.cString) #expect(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
XCTAssertEqual(pointer, mymapPointer) #expect(pointer == mymapPointer)
} }
} }
XCTAssertEqual(mymap?.values[0]?.cString, vec[1]?.cString) #expect(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
XCTAssertEqual(pointer, mymapPointer) #expect(pointer == mymapPointer)
} }
} }
} }
@@ -127,7 +131,7 @@ final class FlexBuffersReaderTests: XCTestCase {
#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: #file) let filePath = URL(filePath: #filePath)
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
@@ -136,5 +140,4 @@ final class FlexBuffersReaderTests: XCTestCase {
return FileManager.default.currentDirectoryPath return FileManager.default.currentDirectoryPath
#endif #endif
} }
} }

View File

@@ -16,10 +16,12 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Foundation
import Testing
final class FlexBuffersStringTests: XCTestCase { struct FlexBuffersStringTests {
@Test
func testEncodingUnicodeString() { func testEncodingUnicodeString() {
let text = "プ画をみて✋" let text = "プ画をみて✋"
@@ -38,6 +40,6 @@ final class FlexBuffersStringTests: XCTestCase {
return String(data: data, encoding: .unicode) return String(data: data, encoding: .unicode)
} }
XCTAssertEqual(builtString, text) #expect(builtString == text)
} }
} }

View File

@@ -16,9 +16,10 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Testing
final class FlexBuffersWriterTests: XCTestCase { struct FlexBuffersWriterTests {
@Test
func testDeallocation() { func testDeallocation() {
let buf: ByteBuffer = { let buf: ByteBuffer = {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
@@ -28,12 +29,13 @@ final class FlexBuffersWriterTests: XCTestCase {
}() }()
buf.withUnsafeBytes { buf.withUnsafeBytes {
XCTAssertEqual( #expect(
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 {
@@ -45,8 +47,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -55,6 +57,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testAddingVectorOfUnsignedScalars() { func testAddingVectorOfUnsignedScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -66,8 +69,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -78,6 +81,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testAddingVectorOfBools() { func testAddingVectorOfBools() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -89,13 +93,14 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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 {
@@ -106,8 +111,8 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -117,6 +122,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testSharingKeyWithinMap() { func testSharingKeyWithinMap() {
var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings) var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings)
fbx.map { fbx.map {
@@ -128,8 +134,8 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -139,19 +145,21 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testNestingVectorInMap() { func testNestingVectorInMap() {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -165,14 +173,15 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -209,14 +218,15 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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 {
@@ -240,8 +250,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
Array($0), Array($0) ==
allTypesGolden) allTypesGolden)
// swiftformat:enable all // swiftformat:enable all
} }

View File

@@ -15,7 +15,7 @@
*/ */
import Foundation import Foundation
import XCTest import Testing
@testable import FlatBuffers @testable import FlatBuffers
@@ -24,8 +24,9 @@ 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
class FlatBuffersMonsterWriterTests: XCTestCase { struct FlatBuffersMonsterWriterTests {
@Test
func testData() { func testData() {
// swiftformat:disable all // swiftformat:disable all
let data: [UInt8] = [ let data: [UInt8] = [
@@ -47,11 +48,12 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -75,11 +77,12 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -98,11 +101,12 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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
XCTAssertEqual( #expect(
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,
@@ -123,6 +127,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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")
@@ -132,10 +137,11 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
XCTAssertNil(newMonster.pos) #expect(newMonster.pos == nil)
XCTAssertEqual(newMonster.name, "Frodo") #expect(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")
@@ -155,10 +161,11 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var buffer = fbb.sizedBuffer var buffer = fbb.sizedBuffer
let newMonster: Monster = getRoot(byteBuffer: &buffer) let newMonster: Monster = getRoot(byteBuffer: &buffer)
XCTAssertEqual(newMonster.pos!.x, 10) #expect(newMonster.pos!.x == 10)
XCTAssertEqual(newMonster.name, "Barney") #expect(newMonster.name == "Barney")
} }
@Test
func testReadMonsterFromUnsafePointerWithoutCopying() { func testReadMonsterFromUnsafePointerWithoutCopying() {
// swiftformat:disable all // swiftformat:disable all
var array: [UInt8] = [ var array: [UInt8] = [
@@ -190,6 +197,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
@@ -205,37 +213,41 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
let monster: Monster = getRoot(byteBuffer: &buffer) let monster: Monster = getRoot(byteBuffer: &buffer)
let values = monster.testarrayofbools let values = monster.testarrayofbools
XCTAssertEqual(boolArray.count, values.count) #expect(boolArray.count == values.count)
for (index, bool) in monster.testarrayofbools.enumerated() { for (index, bool) in monster.testarrayofbools.enumerated() {
XCTAssertEqual(bool, boolArray[index]) #expect(bool == boolArray[index])
} }
} }
func readVerifiedMonster(fb: ByteBuffer) { func readVerifiedMonster(fb: ByteBuffer) {
var byteBuffer = fb var byteBuffer = fb
XCTAssertNoThrow( do {
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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
XCTAssertEqual(testAligned(), true) #expect(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 {
XCTFail("Base pointer is not defined") Issue.record("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -244,13 +256,14 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
assumingMemoryBound: unlignedPtr, assumingMemoryBound: unlignedPtr,
capacity: ptr.count - 1) capacity: ptr.count - 1)
var monster: Monster = getRoot(byteBuffer: &bytes) var monster: Monster = getRoot(byteBuffer: &bytes)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
XCTAssertEqual(testUnaligned(), true) #expect(testUnaligned() == true)
} }
@Test
func testReadingRemovedSizeUnalignedBuffer() { func testReadingRemovedSizeUnalignedBuffer() {
// Aligned read // Aligned read
let fbb = createMonster(withPrefix: true) let fbb = createMonster(withPrefix: true)
@@ -259,7 +272,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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 {
XCTFail("Base pointer is not defined") Issue.record("Base pointer is not defined")
return false return false
} }
baseAddress = baseAddress.advanced(by: 1) baseAddress = baseAddress.advanced(by: 1)
@@ -269,13 +282,14 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
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)
self.readFlatbufferMonster(monster: &monster) readFlatbufferMonster(monster: &monster)
return true return true
} }
} }
XCTAssertEqual(testUnaligned(), true) #expect(testUnaligned() == true)
} }
@Test
func testForceRetainedObject() { func testForceRetainedObject() {
let byteBuffer = { let byteBuffer = {
// swiftformat:disable all // swiftformat:disable all
@@ -381,95 +395,95 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
var fb = fb var fb = fb
let monster: Monster = getRoot(byteBuffer: &fb) let monster: Monster = getRoot(byteBuffer: &fb)
XCTAssertFalse(monster.mutate(mana: 10)) #expect(monster.mutate(mana: 10) == false)
XCTAssertEqual(monster.testarrayoftables[0].name, "Barney") #expect(monster.testarrayoftables[0].name == "Barney")
XCTAssertEqual(monster.testarrayoftables[1].name, "Frodo") #expect(monster.testarrayoftables[1].name == "Frodo")
XCTAssertEqual(monster.testarrayoftables[2].name, "Wilma") #expect(monster.testarrayoftables[2].name == "Wilma")
// Example of searching for a table by the key // Example of searching for a table by the key
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Frodo")) #expect(monster.testarrayoftablesBy(key: "Frodo") != nil)
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Barney")) #expect(monster.testarrayoftablesBy(key: "Barney") != nil)
XCTAssertNotNil(monster.testarrayoftablesBy(key: "Wilma")) #expect(monster.testarrayoftablesBy(key: "Wilma") != nil)
XCTAssertEqual(monster.testType, .monster) #expect(monster.testType == .monster)
XCTAssertEqual(monster.mutate(inventory: 1, at: 0), true) #expect(monster.mutate(inventory: 1, at: 0) == true)
XCTAssertEqual(monster.mutate(inventory: 2, at: 1), true) #expect(monster.mutate(inventory: 2, at: 1) == true)
XCTAssertEqual(monster.mutate(inventory: 3, at: 2), true) #expect(monster.mutate(inventory: 3, at: 2) == true)
XCTAssertEqual(monster.mutate(inventory: 4, at: 3), true) #expect(monster.mutate(inventory: 4, at: 3) == true)
XCTAssertEqual(monster.mutate(inventory: 5, at: 4), true) #expect(monster.mutate(inventory: 5, at: 4) == true)
for i in 0..<monster.inventory.count { for i in 0..<monster.inventory.count {
XCTAssertEqual(monster.inventory[i], Byte(i + 1)) #expect(monster.inventory[i] == Byte(i + 1))
} }
XCTAssertEqual(monster.mutate(inventory: 0, at: 0), true) #expect(monster.mutate(inventory: 0, at: 0) == true)
XCTAssertEqual(monster.mutate(inventory: 1, at: 1), true) #expect(monster.mutate(inventory: 1, at: 1) == true)
XCTAssertEqual(monster.mutate(inventory: 2, at: 2), true) #expect(monster.mutate(inventory: 2, at: 2) == true)
XCTAssertEqual(monster.mutate(inventory: 3, at: 3), true) #expect(monster.mutate(inventory: 3, at: 3) == true)
XCTAssertEqual(monster.mutate(inventory: 4, at: 4), true) #expect(monster.mutate(inventory: 4, at: 4) == true)
let vec = monster.mutablePos let vec = monster.mutablePos
XCTAssertEqual(vec?.x, 1) #expect(vec?.x == 1)
XCTAssertTrue(vec?.mutate(x: 55.0) ?? false) #expect(vec?.mutate(x: 55.0) == true)
XCTAssertTrue(vec?.mutate(test1: 55) ?? false) #expect(vec?.mutate(test1: 55) == true)
XCTAssertEqual(vec?.x, 55.0) #expect(vec?.x == 55.0)
XCTAssertEqual(vec?.test1, 55.0) #expect(vec?.test1 == 55.0)
XCTAssertTrue(vec?.mutate(x: 1) ?? false) #expect(vec?.mutate(x: 1) == true)
XCTAssertEqual(vec?.x, 1) #expect(vec?.x == 1)
XCTAssertTrue(vec?.mutate(test1: 3) ?? false) #expect(vec?.mutate(test1: 3) == true)
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
let orignalValues = mutableTest4[0].a let orignalValues = mutableTest4[0].a
XCTAssertEqual(mutableTest4[0].mutate(a: 100), true) #expect(mutableTest4[0].mutate(a: 100) == true)
XCTAssertNotEqual(monster.test4[0].a, orignalValues) #expect(monster.test4[0].a != orignalValues)
XCTAssertEqual(monster.test4[0].a, 100) #expect(monster.test4[0].a == 100)
XCTAssertEqual(mutableTest4[0].mutate(a: orignalValues), true) #expect(mutableTest4[0].mutate(a: orignalValues) == true)
} }
func readFlatbufferMonster(monster: inout MyGame_Example_Monster) { func readFlatbufferMonster(monster: inout MyGame_Example_Monster) {
XCTAssertEqual(monster.hp, 80) #expect(monster.hp == 80)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.name, "MyMonster") #expect(monster.name == "MyMonster")
let pos = monster.pos let pos = monster.pos
XCTAssertEqual(pos?.x, 1) #expect(pos?.x == 1)
XCTAssertEqual(pos?.y, 2) #expect(pos?.y == 2)
XCTAssertEqual(pos?.z, 3) #expect(pos?.z == 3)
XCTAssertEqual(pos?.test1, 3) #expect(pos?.test1 == 3)
XCTAssertEqual(pos?.test2, .green) #expect(pos?.test2 == .green)
let test = pos?.test3 let test = pos?.test3
XCTAssertEqual(test?.a, 5) #expect(test?.a == 5)
XCTAssertEqual(test?.b, 6) #expect(test?.b == 6)
XCTAssertEqual(monster.testType, .monster) #expect(monster.testType == .monster)
let monster2 = monster.test(type: Monster.self) let monster2 = monster.test(type: Monster.self)
XCTAssertEqual(monster2?.name, "Fred") #expect(monster2?.name == "Fred")
XCTAssertEqual(monster.mutate(mana: 10), false) #expect(monster.mutate(mana: 10) == false)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.inventory.count, 5) #expect(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
} }
XCTAssertEqual(sum, 10) #expect(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]
} }
XCTAssertEqual(sum, 10) #expect(sum == 10)
} }
XCTAssertEqual(monster.test4.count, 2) #expect(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)
} }
XCTAssertEqual(sum0, 100) #expect(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 }
@@ -485,7 +499,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
pointerSum += Int(bindedMemory[pointee].a) + pointerSum += Int(bindedMemory[pointee].a) +
Int(bindedMemory[pointee].b) Int(bindedMemory[pointee].b)
} }
XCTAssertEqual(pointerSum, 100) #expect(pointerSum == 100)
} }
let mutableTest4 = monster.mutableTest4 let mutableTest4 = monster.mutableTest4
@@ -493,87 +507,84 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
for test0 in mutableTest4 { for test0 in mutableTest4 {
sum2 += Int(test0.a) + Int(test0.b) sum2 += Int(test0.a) + Int(test0.b)
} }
XCTAssertEqual(sum2, 100) #expect(sum2 == 100)
let stringArray = monster.testarrayofstring let stringArray = monster.testarrayofstring
XCTAssertEqual(stringArray.count, 2) #expect(stringArray.count == 2)
XCTAssertEqual(stringArray[0], "test1") #expect(stringArray[0] == "test1")
XCTAssertEqual(stringArray[1], "test2") #expect(stringArray[1] == "test2")
XCTAssertEqual(monster.testbool, true) #expect(monster.testbool == true)
let array = monster.nameSegmentArray let array = monster.nameSegmentArray
XCTAssertEqual(String(bytes: array ?? [], encoding: .utf8), "MyMonster") #expect(String(bytes: array ?? [], encoding: .utf8) == "MyMonster")
if 0 == monster.testarrayofbools.count { if 0 == monster.testarrayofbools.count {
XCTAssertEqual(monster.testarrayofbools.isEmpty, true) #expect(monster.testarrayofbools.isEmpty == true)
} else { } else {
XCTAssertEqual(monster.testarrayofbools.isEmpty, false) #expect(monster.testarrayofbools.isEmpty == false)
} }
} }
func readObjectApi(monster: MyGame_Example_MonsterT) { func readObjectApi(monster: MyGame_Example_MonsterT) {
XCTAssertEqual(monster.hp, 80) #expect(monster.hp == 80)
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.name, "MyMonster") #expect(monster.name == "MyMonster")
let pos = monster.pos let pos = monster.pos
XCTAssertEqual(pos?.x, 1) #expect(pos?.x == 1)
XCTAssertEqual(pos?.y, 2) #expect(pos?.y == 2)
XCTAssertEqual(pos?.z, 3) #expect(pos?.z == 3)
XCTAssertEqual(pos?.test1, 3) #expect(pos?.test1 == 3)
XCTAssertEqual(pos?.test2, .green) #expect(pos?.test2 == .green)
let test = pos?.test3 let test = pos?.test3
XCTAssertEqual(test?.a, 5) #expect(test?.a == 5)
XCTAssertEqual(test?.b, 6) #expect(test?.b == 6)
let monster2 = monster.test?.value as? MyGame_Example_MonsterT let monster2 = monster.test?.value as? MyGame_Example_MonsterT
XCTAssertEqual(monster2?.name, "Fred") #expect(monster2?.name == "Fred")
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
monster.mana = 10 monster.mana = 10
XCTAssertEqual(monster.mana, 10) #expect(monster.mana == 10)
monster.mana = 150 monster.mana = 150
XCTAssertEqual(monster.mana, 150) #expect(monster.mana == 150)
XCTAssertEqual(monster.inventory.count, 5) #expect(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
} }
XCTAssertEqual(sum, 10) #expect(sum == 10)
XCTAssertEqual(monster.test4.count, 2) #expect(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)
} }
XCTAssertEqual(sum0, 100) #expect(sum0 == 100)
XCTAssertEqual(monster.testbool, true) #expect(monster.testbool == true)
} }
func testEncoding() { @Test
func testEncoding() throws {
let fbb = createMonster(withPrefix: false) let fbb = createMonster(withPrefix: false)
var sizedBuffer = fbb.sizedBuffer var sizedBuffer = fbb.sizedBuffer
do { struct Test: Decodable {
struct Test: Decodable { struct Pos: Decodable {
struct Pos: Decodable { let x, y, z: Int
let x, y, z: Int
}
let hp: Int
let inventory: [UInt8]
let name: String
let pos: Pos
} }
let reader: Monster = try getCheckedRoot(byteBuffer: &sizedBuffer) let hp: Int
let encoder = JSONEncoder() let inventory: [UInt8]
encoder.keyEncodingStrategy = .convertToSnakeCase let name: String
let data = try encoder.encode(reader) let pos: Pos
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 {

View File

@@ -662,7 +662,7 @@ public struct MyGame_Example_StructOfStructsOfStructs_Mutable: FlatBufferStruct,
} }
} }
public struct MyGame_InParentNamespace: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_InParentNamespace: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example2_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Stat: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Referrable: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_Monster: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct MyGame_Example_TypeAliases: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -16,17 +16,19 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Foundation
import Testing
final class FlexBuffersJSONTests: XCTestCase { struct FlexBuffersJSONTests {
@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
XCTAssertEqual( #expect(
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
@@ -37,15 +39,15 @@ final class FlexBuffersJSONTests: XCTestCase {
with: data, with: data,
options: []) as! [String: Any] options: []) as! [String: Any]
XCTAssertEqual(decodedData["bar"] as! [Int], [1, 2, 3]) #expect(decodedData["bar"] as! [Int] == [1, 2, 3])
XCTAssertEqual(decodedData["bar3"] as! [Int], [1, 2, 3]) #expect(decodedData["bar3"] as! [Int] == [1, 2, 3])
let vec: [Any] = decodedData["vec"] as! [Any] let vec: [Any] = decodedData["vec"] as! [Any]
XCTAssertEqual(vec[0] as! Int, -100) #expect(vec[0] as! Int == -100)
XCTAssertEqual(vec[1] as! String, "Fred") #expect(vec[1] as! String == "Fred")
XCTAssertEqual(vec[2] as! Double, 4.0) #expect(vec[2] as! Double == 4.0)
XCTAssertEqual(vec[3] as! String, "M") #expect(vec[3] as! String == "M")
XCTAssertEqual(vec[4] as! Bool, false) #expect(vec[4] as! Bool == false)
XCTAssertEqual(vec[5] as! Double, 4.0) #expect(vec[5] as! Double == 4.0)
} }
} }

View File

@@ -15,22 +15,26 @@
*/ */
import Common import Common
import XCTest import Foundation
import Testing
@testable import FlexBuffers @testable import FlexBuffers
final class FlexBuffersReaderTests: XCTestCase { struct FlexBuffersReaderTests {
@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,
@@ -38,87 +42,87 @@ final class FlexBuffersReaderTests: XCTestCase {
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray)) try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray))
XCTAssertEqual(fbx.capacity, 512) #expect(fbx.capacity == 512)
fbx.reset() fbx.reset()
XCTAssertEqual(fbx.writerIndex, 0) #expect(fbx.writerIndex == 0)
XCTAssertEqual(fbx.capacity, 8) #expect(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)
XCTAssertEqual(fbx.writerIndex, 0) #expect(fbx.writerIndex == 0)
XCTAssertEqual(fbx.capacity, 512) #expect(fbx.capacity == 512)
write(fbx: &fbx) write(fbx: &fbx)
try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray)) try validate(buffer: ByteBuffer(bytes: fbx.sizedByteArray))
XCTAssertEqual(fbx.capacity, 512) #expect(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)!
XCTAssertEqual(reference.type, .map) #expect(reference.type == .map)
let map = reference.map! let map = reference.map!
XCTAssertEqual(map.count, 7) #expect(map.count == 7)
let vecRef = map["vec"]! let vecRef = map["vec"]!
XCTAssertEqual(vecRef.type, .vector) #expect(vecRef.type == .vector)
let vec = vecRef.vector! let vec = vecRef.vector!
XCTAssertEqual(vec.count, 6) #expect(vec.count == 6)
XCTAssertEqual(vec[0]?.type, .int) #expect(vec[0]?.type == .int)
XCTAssertEqual(vec[0]?.int, -100) #expect(vec[0]?.int == -100)
XCTAssertEqual(vec[1]?.type, .string) #expect(vec[1]?.type == .string)
XCTAssertEqual(vec[1]?.cString, "Fred") #expect(vec[1]?.cString == "Fred")
XCTAssertNil(vec[1]?.int) #expect(vec[1]?.int == nil)
XCTAssertEqual(vec[2]?.double, 4.0) #expect(vec[2]?.double == 4.0)
XCTAssertTrue(vec[3]?.type == .blob) #expect(vec[3]?.type == .blob)
let blob = vec[3]!.blob { pointer in let blob = vec[3]!.blob { pointer in
Array(pointer) Array(pointer)
} }
XCTAssertEqual(blob?.count, 1) #expect(blob?.count == 1)
XCTAssertEqual(blob?[0], 77) #expect(blob?[0] == 77)
XCTAssertEqual(vec[4]?.type, .bool) #expect(vec[4]?.type == .bool)
XCTAssertEqual(vec[4]?.bool, false) #expect(vec[4]?.bool == false)
XCTAssertEqual(vec[5]?.double, 4.0) // Shared with vec[2] #expect(vec[5]?.double == 4.0) // Shared with vec[2]
let barVec = map["bar"]!.typedVector! let barVec = map["bar"]!.typedVector!
XCTAssertEqual(barVec.count, 3) #expect(barVec.count == 3)
XCTAssertEqual(barVec[2]?.int, 3) #expect(barVec[2]?.int == 3)
XCTAssertEqual(barVec[2]?.asInt(), UInt8(3)) #expect(barVec[2]?.asInt() == UInt8(3))
let fixedVec = map["bar3"]!.fixedTypedVector! let fixedVec = map["bar3"]!.fixedTypedVector!
XCTAssertEqual(fixedVec.count, 3) #expect(fixedVec.count == 3)
XCTAssertEqual(fixedVec[2]?.int, 3) #expect(fixedVec[2]?.int == 3)
XCTAssertEqual(fixedVec[2]?.asInt(), UInt8(3)) #expect(fixedVec[2]?.asInt() == UInt8(3))
XCTAssertEqual(map["bool"]?.bool, true) #expect(map["bool"]?.bool == true)
let boolsVector = map["bools"]!.typedVector! let boolsVector = map["bools"]!.typedVector!
XCTAssertEqual(boolsVector.type, .bool) #expect(boolsVector.type == .bool)
XCTAssertEqual(boolsVector[0]?.bool, true) #expect(boolsVector[0]?.bool == true)
XCTAssertEqual(boolsVector[1]?.bool, false) #expect(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 {
XCTAssertEqual(buff.load(fromByteOffset: i, as: Bool.self), bools[i]) #expect(buff.load(fromByteOffset: i, as: Bool.self) == bools[i])
} }
} }
XCTAssertEqual(map["foo"]?.double, 100) #expect(map["foo"]?.double == 100)
XCTAssertNil(map["unknown"]) #expect(map["unknown"] == nil)
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
XCTAssertEqual(mymap?.keys[0]?.cString, map.keys[4]?.cString) #expect(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
XCTAssertEqual(pointer, mymapPointer) #expect(pointer == mymapPointer)
} }
} }
XCTAssertEqual(mymap?.values[0]?.cString, vec[1]?.cString) #expect(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
XCTAssertEqual(pointer, mymapPointer) #expect(pointer == mymapPointer)
} }
} }
} }
@@ -127,7 +131,7 @@ final class FlexBuffersReaderTests: XCTestCase {
#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: #file) let filePath = URL(filePath: #filePath)
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()
.deletingLastPathComponent() .deletingLastPathComponent()

View File

@@ -16,10 +16,12 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Foundation
import Testing
final class FlexBuffersStringTests: XCTestCase { struct FlexBuffersStringTests {
@Test
func testEncodingUnicodeString() { func testEncodingUnicodeString() {
let text = "プ画をみて✋" let text = "プ画をみて✋"
@@ -38,6 +40,6 @@ final class FlexBuffersStringTests: XCTestCase {
return String(data: data, encoding: .unicode) return String(data: data, encoding: .unicode)
} }
XCTAssertEqual(builtString, text) #expect(builtString == text)
} }
} }

View File

@@ -16,9 +16,10 @@
import Common import Common
import FlexBuffers import FlexBuffers
import XCTest import Testing
final class FlexBuffersWriterTests: XCTestCase { struct FlexBuffersWriterTests {
@Test
func testDeallocation() { func testDeallocation() {
let buf: ByteBuffer = { let buf: ByteBuffer = {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
@@ -28,12 +29,13 @@ final class FlexBuffersWriterTests: XCTestCase {
}() }()
buf.withUnsafeBytes { buf.withUnsafeBytes {
XCTAssertEqual( #expect(
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 {
@@ -45,8 +47,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -55,6 +57,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testAddingVectorOfUnsignedScalars() { func testAddingVectorOfUnsignedScalars() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -66,8 +69,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -78,6 +81,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testAddingVectorOfBools() { func testAddingVectorOfBools() {
var fbx = FlexBuffersWriter() var fbx = FlexBuffersWriter()
fbx.vector { fbx.vector {
@@ -89,13 +93,14 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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 {
@@ -106,8 +111,8 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -117,6 +122,7 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testSharingKeyWithinMap() { func testSharingKeyWithinMap() {
var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings) var fbx = FlexBuffersWriter(initialSize: 1000, flags: .shareKeysAndStrings)
fbx.map { fbx.map {
@@ -128,8 +134,8 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -139,19 +145,21 @@ final class FlexBuffersWriterTests: XCTestCase {
} }
} }
@Test
func testNestingVectorInMap() { func testNestingVectorInMap() {
let buf: ByteBuffer = createSizedBuffer() let buf: ByteBuffer = createSizedBuffer()
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -165,14 +173,15 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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,
@@ -209,14 +218,15 @@ final class FlexBuffersWriterTests: XCTestCase {
let buf: ByteBuffer = fbx.sizedByteBuffer let buf: ByteBuffer = fbx.sizedByteBuffer
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
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 {
@@ -240,8 +250,8 @@ final class FlexBuffersWriterTests: XCTestCase {
buf.withUnsafeBytes { buf.withUnsafeBytes {
// swiftformat:disable all // swiftformat:disable all
XCTAssertEqual( #expect(
Array($0), Array($0) ==
allTypesGolden) allTypesGolden)
// swiftformat:enable all // swiftformat:enable all
} }

View File

@@ -3,12 +3,12 @@
// swiftformat:disable all // swiftformat:disable all
#if canImport(Common) #if canImport(Common)
@_implementationOnly import Common internal import Common
#endif #endif
@_implementationOnly import FlatBuffers internal import FlatBuffers
internal struct Message: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { internal struct Message: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -68,7 +68,7 @@ public struct BytesCount_Mutable: FlatBufferStruct, FlatbuffersVectorInitializab
} }
} }
public struct InternalMessage: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct InternalMessage: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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: FlatBufferTable, FlatbuffersVectorInitializable, Verifiable, ObjectAPIPacker { public struct Message: FlatBufferVerifiableTable, FlatbuffersVectorInitializable, 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 }

View File

@@ -1774,6 +1774,7 @@ 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);

View File

@@ -62,16 +62,10 @@ def flatc(
# Execute esbuild with the specified parameters # Execute esbuild with the specified parameters
def esbuild(input, output): def esbuild(input, output):
cmd = ["esbuild", input, "--outfile=" + output] cmd = ["../../node_modules/.bin/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",
@@ -228,12 +222,12 @@ flatc(
) )
print("Running TypeScript Compiler...") print("Running TypeScript Compiler...")
check_call(["tsc"]) check_call(["../../node_modules/.bin/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(["tsc", "-p", "./tsconfig.node.json"]) check_call(["../../node_modules/.bin/tsc", "-p", "./tsconfig.node.json"])
NODE_CMD = ["node"] NODE_CMD = ["node"]

View File

@@ -1,6 +1,6 @@
{ {
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"flatbuffers": "../../" "flatbuffers": "workspace:*"
} }
} }

View File

@@ -1,10 +0,0 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
flatbuffers:
specifier: ../../
version: link:../..