Compare commits

..
Author SHA1 Message Date
dependabot[bot] 197e659b4d Bump actions/checkout from 6 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-22 13:45:04 +00:00
blindspot 81edeb17d9 swift 6.0+ performance tweaks 3x-6x (#9067)
* start/stop measurements

* tweaks

* add 6.0 annotations

* remove some inlines

* address feedback

* address wasi + let

* adopt flex buffers

* flex buffers benchmarks
2026-06-18 15:23:53 +02:00
Jakob Kordež 5982eb6495 Lock pnpm version to 10 in CI workflow (#9142) 2026-06-18 11:59:24 +02:00
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
18 changed files with 363 additions and 93 deletions
+33 -33
View File
@@ -30,7 +30,7 @@ jobs:
cxx: [g++-13, clang++-18]
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_STATIC_FLATC=ON .
- name: build
@@ -51,7 +51,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: zip Linux.flatc.binary.${{ matrix.cxx }}.zip flatc
- name: Release zip file
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Linux.flatc.binary.${{ matrix.cxx }}.zip
@@ -68,7 +68,7 @@ jobs:
name: Build Linux with -DFLATBUFFERS_NO_FILE_TESTS
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: CXX=clang++-18 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_CXX_FLAGS="-DFLATBUFFERS_NO_FILE_TESTS" .
- name: build
@@ -80,7 +80,7 @@ jobs:
name: Build Linux with out-of-source build location
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: make build directory
run: mkdir build
- name: cmake
@@ -112,7 +112,7 @@ jobs:
std: 23
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: >
CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles"
@@ -135,7 +135,7 @@ jobs:
std: [11, 14, 17, 20, 23]
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
- name: cmake
@@ -160,7 +160,7 @@ jobs:
name: Build Windows 2022
runs-on: windows-2022
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
- name: cmake
@@ -179,7 +179,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: move Release/flatc.exe . && Compress-Archive flatc.exe Windows.flatc.binary.zip
- name: Release binary
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Windows.flatc.binary.zip
@@ -200,7 +200,7 @@ jobs:
'-p:EnableSpanT=true,UnsafeByteBuffer=true'
]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v5
with:
@@ -229,7 +229,7 @@ jobs:
name: Build Mac (for Intel)
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
@@ -255,7 +255,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc
- name: Release binary
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: MacIntel.flatc.binary.zip
@@ -272,7 +272,7 @@ jobs:
name: Build Mac (universal build)
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
- name: build
@@ -298,7 +298,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc
- name: Release binary
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Mac.flatc.binary.zip
@@ -312,7 +312,7 @@ jobs:
if: false #disabled due to continual failure
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: set up Java
uses: actions/setup-java@v5
with:
@@ -336,7 +336,7 @@ jobs:
matrix:
cxx: [g++-13, clang++-18]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
- name: Generate
@@ -348,7 +348,7 @@ jobs:
name: Check Generated Code on Windows
runs-on: windows-2022
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
- name: cmake
@@ -367,7 +367,7 @@ jobs:
matrix:
cxx: [g++-13]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
- name: Run benchmarks
@@ -382,7 +382,7 @@ jobs:
name: Build Java
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: test
working-directory: java
run: mvn test
@@ -392,7 +392,7 @@ jobs:
runs-on: macos-15
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: set up Java
uses: actions/setup-java@v5
with:
@@ -415,7 +415,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: set up Java
uses: actions/setup-java@v5
with:
@@ -439,7 +439,7 @@ jobs:
name: Build Rust Linux
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: test
working-directory: tests
run: bash RustTest.sh
@@ -448,7 +448,7 @@ jobs:
name: Build Rust Windows
runs-on: windows-2022
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: test
working-directory: tests
run: ./RustTest.bat
@@ -457,7 +457,7 @@ jobs:
name: Build Python
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -469,7 +469,7 @@ jobs:
name: Build Go
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -481,7 +481,7 @@ jobs:
name: Build PHP
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
@@ -498,7 +498,7 @@ jobs:
swift: ["6.0", "6.1", "6.2"]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: swift-actions/setup-swift@v2
with:
swift-version: ${{ matrix.swift }}
@@ -511,7 +511,7 @@ jobs:
name: Test swift windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: SwiftyLab/setup-swift@latest
with:
swift-version: '6.1'
@@ -522,7 +522,7 @@ jobs:
name: Test Swift Wasm
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: swift-actions/setup-swift@v2
with:
swift-version: 6.2.1
@@ -540,12 +540,12 @@ jobs:
name: Build TS
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
- name: pnpm
run: npm install -g pnpm
run: npm install -g pnpm@10
- name: deps
run: pnpm i
- name: compile
@@ -559,7 +559,7 @@ jobs:
name: Build Dart
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: dart-lang/setup-dart@v1
with:
sdk: stable
@@ -574,7 +574,7 @@ jobs:
name: Build Nim
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: flatc
# FIXME: make test script not rely on flatc
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
@@ -590,7 +590,7 @@ jobs:
name: Bazel
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
# Explicitly use 8.5.1 until we can update or https://github.com/actions/runner-images/issues/13564 is fixed.
- name: Set env
run: >
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
+6 -6
View File
@@ -12,7 +12,7 @@ jobs:
name: Publish NPM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
with:
node-version: '20.x'
@@ -29,7 +29,7 @@ jobs:
run:
working-directory: ./python
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: '3.10'
@@ -57,7 +57,7 @@ jobs:
run:
working-directory: ./net/flatbuffers
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
@@ -80,7 +80,7 @@ jobs:
run:
working-directory: ./java
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Set up Maven Central Repository
uses: actions/setup-java@v5
@@ -108,7 +108,7 @@ jobs:
run:
working-directory: ./kotlin
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Set up Maven Central Repository
uses: actions/setup-java@v5
with:
@@ -133,7 +133,7 @@ jobs:
name: Publish crates.io
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
@@ -97,6 +97,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
}
benchmark.stopMeasurement()
}
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
@@ -105,6 +106,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.clear())
}
benchmark.stopMeasurement()
}
Benchmark("Strings 10") { benchmark in
@@ -113,6 +115,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str10))
}
benchmark.stopMeasurement()
}
Benchmark("Strings 100") { benchmark in
@@ -121,6 +124,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(string: str100))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 1 Bytes") { benchmark in
@@ -129,6 +133,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 1 Ints") { benchmark in
@@ -137,6 +142,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 Ints") { benchmark in
@@ -145,6 +151,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(ints))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 Bytes") { benchmark in
@@ -153,6 +160,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes))
}
benchmark.stopMeasurement()
}
Benchmark("Vector 100 ContiguousBytes") { benchmark in
@@ -161,6 +169,7 @@ let benchmarks = {
for i in benchmark.scaledIterations {
blackHole(fb.createVector(bytes: bytes))
}
benchmark.stopMeasurement()
}
Benchmark(
@@ -178,6 +187,7 @@ let benchmarks = {
fb.add(offset: off, at: 8)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark(
@@ -190,6 +200,7 @@ let benchmarks = {
let s = fb.startTable(with: 4)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark("Struct") { benchmark in
@@ -198,6 +209,7 @@ let benchmarks = {
for _ in benchmark.scaledIterations {
blackHole(fb.create(struct: array.first!))
}
benchmark.stopMeasurement()
}
Benchmark("Structs") { benchmark in
@@ -219,6 +231,7 @@ let benchmarks = {
fb.add(offset: vector, at: 4)
let root = Offset(offset: fb.endTable(at: start))
blackHole(fb.finish(offset: root))
benchmark.stopMeasurement()
}
Benchmark("Vector of Offsets") { benchmark in
@@ -239,12 +252,15 @@ let benchmarks = {
fb.add(offset: off, at: 2)
blackHole(fb.endTable(at: s))
}
benchmark.stopMeasurement()
}
Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0))
}
benchmark.stopMeasurement()
}
}
@@ -0,0 +1,174 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Benchmark
import FlexBuffers
import Foundation
let benchmarks = {
let data = {
var array = [8888.88, 8888.88]
var data = Data()
array.withUnsafeBytes { ptr in
data.append(contentsOf: ptr)
}
return data
}()
let ints: [Int32] = Array(repeating: 42, count: 100)
let str10 = (0...9).map { _ -> String in "x" }.joined()
let str100 = (0...99).map { _ -> String in "x" }.joined()
// A representative map: 50 keyed scalars, a keyed string and a keyed vector
// of 100 scalars. Used for the realistic decode benchmarks.
let mapBuffer: ByteBuffer = {
var fbx = FlexBuffersWriter(initialSize: 1 << 16)
fbx.map {
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
$0.add(string: "hello world", key: "s")
$0.vector(key: "v") { v in
for x in 0..<100 { v.add(int: x) }
}
}
fbx.finish()
return fbx.sizedByteBuffer
}()
let metrics: [BenchmarkMetric] = [
.cpuTotal,
.wallClock,
.mallocCountTotal,
.releaseCount,
.peakMemoryResident,
]
let maxIterations = 1_000_000
let maxDuration: Duration = .seconds(3)
let megaConfiguration: Benchmark.Configuration = .init(
metrics: metrics,
warmupIterations: 1,
scalingFactor: .mega,
maxDuration: maxDuration,
maxIterations: maxIterations)
Benchmark.defaultConfiguration = megaConfiguration
// Decode (read path)
// Raw scalar read: isolates `read<T: BitwiseCopyable>` and the `let` blob.
Benchmark("Reading Doubles") { benchmark in
let byteBuffer = ByteBuffer(data: data)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
blackHole(byteBuffer.read(def: Double.self, position: 0))
}
benchmark.stopMeasurement()
}
// Realistic decode: resolve root map and read a keyed scalar.
Benchmark("Decode Map Scalar") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
blackHole(map["i25"]?.int)
}
benchmark.stopMeasurement()
}
// Realistic decode: resolve root map and read a keyed string.
Benchmark("Decode Map String") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
blackHole(map["s"]?.string())
}
benchmark.stopMeasurement()
}
// Realistic decode: resolve a nested vector and sum its scalars.
Benchmark("Decode Vector") { benchmark in
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
let map = try! getRoot(buffer: mapBuffer)!.map!
let vector = map["v"]!.vector!
var sum: Int64 = 0
for i in 0..<vector.count {
sum &+= vector[i]?.int ?? 0
}
blackHole(sum)
}
benchmark.stopMeasurement()
}
// Encode (write path)
// Writers are reused with `reset(keepingCapacity:)` so per-iteration
// allocation does not dominate and mask the write-path cost (which is what
// the `@exclusivity(unchecked)` storage pointer affects).
Benchmark("Strings 10") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.add(string: str10)
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Strings 100") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.add(string: str100)
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Encoding Vector Of Ints") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.vector {
$0.create(vector: ints)
}
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
Benchmark("Encoding Map") { benchmark in
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
benchmark.startMeasurement()
for _ in benchmark.scaledIterations {
fbx.map {
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
$0.add(string: "hello world", key: "s")
$0.vector(key: "v") { v in
for x in 0..<100 { v.add(int: x) }
}
}
fbx.finish()
blackHole(fbx.sizedByteBuffer)
fbx.reset(keepingCapacity: true)
}
benchmark.stopMeasurement()
}
}
+10
View File
@@ -39,4 +39,14 @@ let package = Package(
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
.executableTarget(
name: "FlexBuffersBenchmarks",
dependencies: [
.product(name: "FlexBuffers", package: "flatbuffers"),
.product(name: "Benchmark", package: "package-benchmark"),
],
path: "Benchmarks/FlexBuffersBenchmarks",
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
]),
])
+6 -25
View File
@@ -654,34 +654,15 @@ class DartGenerator : public BaseGenerator {
std::string NamespaceAliasFromUnionType(Namespace* root_namespace,
const Type& type) {
const std::vector<std::string> qualified_name_parts =
type.struct_def->defined_namespace->components;
if (std::equal(root_namespace->components.begin(),
root_namespace->components.end(),
qualified_name_parts.begin())) {
const Namespace& type_namespace = *type.struct_def->defined_namespace;
if (root_namespace->components == type_namespace.components) {
return namer_.Type(*type.struct_def);
}
std::string ns;
for (auto it = qualified_name_parts.begin();
it != qualified_name_parts.end(); ++it) {
auto& part = *it;
for (size_t i = 0; i < part.length(); i++) {
if (i && !isdigit(part[i]) && part[i] == CharToUpper(part[i])) {
ns += "_";
ns += CharToLower(part[i]);
} else {
ns += CharToLower(part[i]);
}
}
if (it != qualified_name_parts.end() - 1) {
ns += "_";
}
}
return ns + "." + namer_.Type(*type.struct_def);
const std::string ns = namer_.Namespace(type_namespace);
return ns.empty()
? namer_.Type(*type.struct_def)
: ImportAliasName(ns) + "." + namer_.Type(*type.struct_def);
}
void GenImplementationGetters(
+1 -1
View File
@@ -28,7 +28,7 @@ public let FileIdLength = 4
/// Protocol that All Scalars should conform to
///
/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
public protocol Scalar: Equatable, BitwiseCopyable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}
+46 -9
View File
@@ -27,7 +27,7 @@ public struct ByteBuffer: @unchecked Sendable {
@usableFromInline
final class Storage {
@usableFromInline
enum Blob {
@frozen enum Blob: ~Copyable {
#if !os(WASI)
case data(Data)
case bytes(any ContiguousBytes)
@@ -36,6 +36,40 @@ public struct ByteBuffer: @unchecked Sendable {
case byteBuffer(_InternalByteBuffer)
case array([UInt8])
case pointer(UnsafeMutableRawPointer)
init(_ other: borrowing Blob) {
switch other {
#if !os(WASI)
case .data(let data):
self = .data(data)
case .bytes(let contiguousBytes):
self = .bytes(contiguousBytes)
#endif
case .byteBuffer(let internalByteBuffer):
self = .byteBuffer(internalByteBuffer)
case .array(let array):
self = .array(array)
case .pointer(let unsafeMutableRawPointer):
self = .pointer(unsafeMutableRawPointer)
}
}
var description: String {
switch self {
#if !os(WASI)
case .data(let data):
"data: \(data)"
case .bytes(let contiguousBytes):
"bytes: \(contiguousBytes)"
#endif
case .byteBuffer(let internalByteBuffer):
"byteBuffer: \(internalByteBuffer)"
case .array(let array):
"array: \(array)"
case .pointer(let unsafeMutableRawPointer):
"pointer: \(unsafeMutableRawPointer)"
}
}
}
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -44,7 +78,7 @@ public struct ByteBuffer: @unchecked Sendable {
private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline
var retainedBlob: Blob
let retainedBlob: Blob
@usableFromInline
init(count: Int) {
@@ -57,9 +91,9 @@ public struct ByteBuffer: @unchecked Sendable {
}
@usableFromInline
init(blob: Blob, capacity count: Int) {
init(blob: borrowing Blob, capacity count: Int) {
capacity = count
retainedBlob = blob
retainedBlob = .init(blob)
isOwned = false
}
@@ -150,6 +184,7 @@ public struct ByteBuffer: @unchecked Sendable {
@discardableResult
@inline(__always)
@inlinable
func readWithUnsafeRawPointer<T>(
position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
@@ -278,7 +313,7 @@ public struct ByteBuffer: @unchecked Sendable {
/// - removeBytes: Removes a number of bytes from the current size
@inline(__always)
init(
blob: Storage.Blob,
blob: borrowing Storage.Blob,
count: Int,
removing removeBytes: Int)
{
@@ -318,7 +353,8 @@ public struct ByteBuffer: @unchecked Sendable {
/// - def: Type of the object
/// - position: the index of the object in the buffer
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
@inlinable
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1)
.pointee
@@ -412,7 +448,7 @@ public struct ByteBuffer: @unchecked Sendable {
/// - Parameter removeBytes: the amount of bytes to remove from the current Size
@inline(__always)
public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
assert(removeBytes > 0, "Can NOT remove negative bytes")
assert(removeBytes >= 0, "Can NOT remove negative bytes")
assert(
removeBytes < capacity,
"Can NOT remove more bytes than the ones allocated")
@@ -464,8 +500,9 @@ public struct ByteBuffer: @unchecked Sendable {
extension ByteBuffer: CustomDebugStringConvertible {
public var debugDescription: String {
"""
buffer located at: \(_storage.retainedBlob),
let blobDescription = _storage.retainedBlob.description
return """
buffer located at: \(blobDescription),
with capacity of \(capacity),
{ writtenSize: \(_readerIndex), readerSize: \(reader),
size: \(size) }
@@ -47,7 +47,8 @@ public struct FlatBufferBuilder {
/// A check to see if finish(::) was ever called to retreive data object
private(set) var finished = false
/// A check to see if the buffer should serialize Default values
private var serializeDefaults: Bool
@usableFromInline
let serializeDefaults: Bool
/// Current alignment for the buffer
var _minAlignment: Int = 0 {
@@ -756,6 +757,7 @@ public struct FlatBufferBuilder {
/// - offset: ``Offset`` of another object to be written
/// - position: The predefined position of the object
@inline(__always)
@inlinable
mutating public func add(offset: Offset, at position: VOffset) {
if offset.isEmpty { return }
add(element: refer(to: offset.o), def: 0, at: position)
@@ -794,6 +796,7 @@ public struct FlatBufferBuilder {
/// - def: Default value for that element
/// - position: The predefined position of the element
@inline(__always)
@inlinable
mutating public func add<T: Scalar>(
element: T,
def: T,
@@ -813,6 +816,7 @@ public struct FlatBufferBuilder {
/// - element: Optional element of type scalar
/// - position: The predefined position of the element
@inline(__always)
@inlinable
mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
guard let element = element else { return }
track(offset: push(element: element), at: position)
@@ -825,6 +829,7 @@ public struct FlatBufferBuilder {
/// - Parameter element: Element to insert
/// - returns: position of the Element
@inline(__always)
@inlinable
@discardableResult
mutating public func push<T: Scalar>(element: T) -> UOffset {
let size = MemoryLayout<T>.size
@@ -836,7 +841,8 @@ public struct FlatBufferBuilder {
}
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
@inlinable
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_bb.read(def: def, position: position)
}
}
@@ -18,7 +18,7 @@ import Foundation
/// NativeStruct is a protocol that indicates if the struct is a native `swift` struct
/// since now we will be serializing native structs into the buffer.
public protocol NativeStruct {}
public protocol NativeStruct: BitwiseCopyable {}
public protocol FlatBufferVerifiableNativeStruct: NativeStruct, Verifiable {}
+1 -1
View File
@@ -82,7 +82,7 @@ public struct Table {
/// - Parameters:
/// - type: Type of Element that needs to be read from the buffer
/// - o: Offset of the Element
public func readBuffer<T>(of type: T.Type, at o: Int32) -> T {
public func readBuffer<T: BitwiseCopyable>(of type: T.Type, at o: Int32) -> T {
bb.read(def: T.self, position: Int(o &+ position))
}
+8 -1
View File
@@ -56,8 +56,15 @@ extension Verifiable {
let len: UOffset = try verifier.getValue(at: position)
let intLen = Int(len)
let start = Int(clamping: (position &+ MemoryLayout<Int32>.size).magnitude)
let byteCount = intLen.multipliedReportingOverflow(
by: MemoryLayout<T>.size)
guard !byteCount.overflow else {
throw FlatbuffersErrors.outOfBounds(
position: UInt.max,
end: verifier.capacity)
}
try verifier.isAligned(position: start, type: type.self)
try verifier.rangeInBuffer(position: start, size: intLen)
try verifier.rangeInBuffer(position: start, size: byteCount.partialValue)
return (start, intLen)
}
}
+1 -1
View File
@@ -163,7 +163,7 @@ public struct Verifier {
/// - Parameter position: Current position to be read
/// - Throws: `inBuffer` errors
/// - Returns: a value of type `T` usually a `VTable` or a table offset
internal func getValue<T>(at position: Int) throws -> T {
internal func getValue<T: BitwiseCopyable>(at position: Int) throws -> T {
try inBuffer(position: position, of: T.self)
return _buffer.read(def: T.self, position: position)
}
@@ -30,7 +30,7 @@ struct _InternalByteBuffer {
@usableFromInline
final class Storage {
/// pointer to the start of the buffer object in memory
private(set) var memory: UnsafeMutableRawPointer
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
@usableFromInline
init(count: Int, alignment: Int) {
@@ -333,6 +333,7 @@ struct _InternalByteBuffer {
@discardableResult
@inline(__always)
@usableFromInline
func readWithUnsafeRawPointer<T>(
position: Int,
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
+27 -10
View File
@@ -27,7 +27,7 @@ public struct ByteBuffer {
@usableFromInline
final class Storage {
@usableFromInline
enum Blob {
@frozen enum Blob: ~Copyable {
#if !os(WASI)
case data(Data)
case bytes(any ContiguousBytes)
@@ -36,6 +36,23 @@ public struct ByteBuffer {
case byteBuffer(_InternalByteBuffer)
case array([UInt8])
case pointer(UnsafeMutableRawPointer)
init(_ other: borrowing Blob) {
switch other {
#if !os(WASI)
case .data(let data):
self = .data(data)
case .bytes(let contiguousBytes):
self = .bytes(contiguousBytes)
#endif
case .byteBuffer(let internalByteBuffer):
self = .byteBuffer(internalByteBuffer)
case .array(let array):
self = .array(array)
case .pointer(let unsafeMutableRawPointer):
self = .pointer(unsafeMutableRawPointer)
}
}
}
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
@@ -44,7 +61,7 @@ public struct ByteBuffer {
private let capacity: Int
/// Retained blob of data that requires the storage to retain a pointer to.
@usableFromInline
var retainedBlob: Blob
let retainedBlob: Blob
@usableFromInline
init(count: Int) {
@@ -57,9 +74,9 @@ public struct ByteBuffer {
}
@usableFromInline
init(blob: Blob, capacity count: Int) {
init(blob: borrowing Blob, capacity count: Int) {
capacity = count
retainedBlob = blob
retainedBlob = .init(blob)
isOwned = false
}
@@ -276,7 +293,7 @@ public struct ByteBuffer {
/// - removeBytes: Removes a number of bytes from the current size
@inline(__always)
init(
blob: Storage.Blob,
blob: borrowing Storage.Blob,
count: Int,
removing removeBytes: Int)
{
@@ -316,7 +333,7 @@ public struct ByteBuffer {
/// - def: Type of the object
/// - position: the index of the object in the buffer
@inline(__always)
public func read<T>(def: T.Type, position: Int) -> T {
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
_storage.readWithUnsafeRawPointer(position: position) {
$0.bindMemory(to: T.self, capacity: 1)
.pointee
@@ -360,10 +377,10 @@ public struct ByteBuffer {
@inline(__always)
func readSizedScalar<
T: BinaryInteger,
T1: BinaryInteger,
T2: BinaryInteger,
T3: BinaryInteger,
T4: BinaryInteger
T1: BinaryInteger & BitwiseCopyable,
T2: BinaryInteger & BitwiseCopyable,
T3: BinaryInteger & BitwiseCopyable,
T4: BinaryInteger & BitwiseCopyable
>(
def: T.Type,
t1: T1.Type,
@@ -31,7 +31,7 @@ struct _InternalByteBuffer {
@usableFromInline
final class Storage {
/// pointer to the start of the buffer object in memory
var memory: UnsafeMutableRawPointer
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
@usableFromInline
init(count: Int, alignment: Int) {
@@ -411,6 +411,27 @@ final class FlatbuffersVerifierTests {
}
}
@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() {
let string = "Awesome \\\\t\t\nstring!"