mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-18 22:08:55 +00:00
Compare commits
1 Commits
master
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ffc8d8346 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -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@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: Linux.flatc.binary.${{ matrix.cxx }}.zip
|
||||
@@ -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@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: Windows.flatc.binary.zip
|
||||
@@ -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@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: MacIntel.flatc.binary.zip
|
||||
@@ -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@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: Mac.flatc.binary.zip
|
||||
@@ -545,7 +545,7 @@ jobs:
|
||||
# FIXME: make test script not rely on flatc
|
||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
||||
- name: pnpm
|
||||
run: npm install -g pnpm@10
|
||||
run: npm install -g pnpm
|
||||
- name: deps
|
||||
run: pnpm i
|
||||
- name: compile
|
||||
|
||||
@@ -97,7 +97,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB)))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in
|
||||
@@ -106,7 +105,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.clear())
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Strings 10") { benchmark in
|
||||
@@ -115,7 +113,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.create(string: str10))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Strings 100") { benchmark in
|
||||
@@ -124,7 +121,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.create(string: str100))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Vector 1 Bytes") { benchmark in
|
||||
@@ -133,7 +129,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.createVector(bytes: bytes))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Vector 1 Ints") { benchmark in
|
||||
@@ -142,7 +137,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.createVector(ints))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Vector 100 Ints") { benchmark in
|
||||
@@ -151,7 +145,6 @@ let benchmarks = {
|
||||
for i in benchmark.scaledIterations {
|
||||
blackHole(fb.createVector(ints))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Vector 100 Bytes") { benchmark in
|
||||
@@ -160,7 +153,6 @@ let benchmarks = {
|
||||
for i in benchmark.scaledIterations {
|
||||
blackHole(fb.createVector(bytes))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Vector 100 ContiguousBytes") { benchmark in
|
||||
@@ -169,7 +161,6 @@ let benchmarks = {
|
||||
for i in benchmark.scaledIterations {
|
||||
blackHole(fb.createVector(bytes: bytes))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark(
|
||||
@@ -187,7 +178,6 @@ let benchmarks = {
|
||||
fb.add(offset: off, at: 8)
|
||||
blackHole(fb.endTable(at: s))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark(
|
||||
@@ -200,7 +190,6 @@ let benchmarks = {
|
||||
let s = fb.startTable(with: 4)
|
||||
blackHole(fb.endTable(at: s))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Struct") { benchmark in
|
||||
@@ -209,7 +198,6 @@ let benchmarks = {
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(fb.create(struct: array.first!))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Structs") { benchmark in
|
||||
@@ -231,7 +219,6 @@ 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
|
||||
@@ -252,15 +239,12 @@ 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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Benchmark
|
||||
import FlexBuffers
|
||||
import Foundation
|
||||
|
||||
let benchmarks = {
|
||||
let data = {
|
||||
var array = [8888.88, 8888.88]
|
||||
var data = Data()
|
||||
array.withUnsafeBytes { ptr in
|
||||
data.append(contentsOf: ptr)
|
||||
}
|
||||
return data
|
||||
}()
|
||||
let ints: [Int32] = Array(repeating: 42, count: 100)
|
||||
let str10 = (0...9).map { _ -> String in "x" }.joined()
|
||||
let str100 = (0...99).map { _ -> String in "x" }.joined()
|
||||
|
||||
// A representative map: 50 keyed scalars, a keyed string and a keyed vector
|
||||
// of 100 scalars. Used for the realistic decode benchmarks.
|
||||
let mapBuffer: ByteBuffer = {
|
||||
var fbx = FlexBuffersWriter(initialSize: 1 << 16)
|
||||
fbx.map {
|
||||
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
|
||||
$0.add(string: "hello world", key: "s")
|
||||
$0.vector(key: "v") { v in
|
||||
for x in 0..<100 { v.add(int: x) }
|
||||
}
|
||||
}
|
||||
fbx.finish()
|
||||
return fbx.sizedByteBuffer
|
||||
}()
|
||||
|
||||
let metrics: [BenchmarkMetric] = [
|
||||
.cpuTotal,
|
||||
.wallClock,
|
||||
.mallocCountTotal,
|
||||
.releaseCount,
|
||||
.peakMemoryResident,
|
||||
]
|
||||
let maxIterations = 1_000_000
|
||||
let maxDuration: Duration = .seconds(3)
|
||||
let megaConfiguration: Benchmark.Configuration = .init(
|
||||
metrics: metrics,
|
||||
warmupIterations: 1,
|
||||
scalingFactor: .mega,
|
||||
maxDuration: maxDuration,
|
||||
maxIterations: maxIterations)
|
||||
|
||||
Benchmark.defaultConfiguration = megaConfiguration
|
||||
|
||||
// Decode (read path)
|
||||
|
||||
// Raw scalar read: isolates `read<T: BitwiseCopyable>` and the `let` blob.
|
||||
Benchmark("Reading Doubles") { benchmark in
|
||||
let byteBuffer = ByteBuffer(data: data)
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
blackHole(byteBuffer.read(def: Double.self, position: 0))
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
// Realistic decode: resolve root map and read a keyed scalar.
|
||||
Benchmark("Decode Map Scalar") { benchmark in
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
let map = try! getRoot(buffer: mapBuffer)!.map!
|
||||
blackHole(map["i25"]?.int)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
// Realistic decode: resolve root map and read a keyed string.
|
||||
Benchmark("Decode Map String") { benchmark in
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
let map = try! getRoot(buffer: mapBuffer)!.map!
|
||||
blackHole(map["s"]?.string())
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
// Realistic decode: resolve a nested vector and sum its scalars.
|
||||
Benchmark("Decode Vector") { benchmark in
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
let map = try! getRoot(buffer: mapBuffer)!.map!
|
||||
let vector = map["v"]!.vector!
|
||||
var sum: Int64 = 0
|
||||
for i in 0..<vector.count {
|
||||
sum &+= vector[i]?.int ?? 0
|
||||
}
|
||||
blackHole(sum)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
// Encode (write path)
|
||||
// Writers are reused with `reset(keepingCapacity:)` so per-iteration
|
||||
// allocation does not dominate and mask the write-path cost (which is what
|
||||
// the `@exclusivity(unchecked)` storage pointer affects).
|
||||
|
||||
Benchmark("Strings 10") { benchmark in
|
||||
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
fbx.add(string: str10)
|
||||
fbx.finish()
|
||||
blackHole(fbx.sizedByteBuffer)
|
||||
fbx.reset(keepingCapacity: true)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Strings 100") { benchmark in
|
||||
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
fbx.add(string: str100)
|
||||
fbx.finish()
|
||||
blackHole(fbx.sizedByteBuffer)
|
||||
fbx.reset(keepingCapacity: true)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Encoding Vector Of Ints") { benchmark in
|
||||
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
fbx.vector {
|
||||
$0.create(vector: ints)
|
||||
}
|
||||
fbx.finish()
|
||||
blackHole(fbx.sizedByteBuffer)
|
||||
fbx.reset(keepingCapacity: true)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
|
||||
Benchmark("Encoding Map") { benchmark in
|
||||
var fbx = FlexBuffersWriter(initialSize: 1 << 20)
|
||||
benchmark.startMeasurement()
|
||||
for _ in benchmark.scaledIterations {
|
||||
fbx.map {
|
||||
for i in 0..<50 { $0.add(int: i, key: "i\(i)") }
|
||||
$0.add(string: "hello world", key: "s")
|
||||
$0.vector(key: "v") { v in
|
||||
for x in 0..<100 { v.add(int: x) }
|
||||
}
|
||||
}
|
||||
fbx.finish()
|
||||
blackHole(fbx.sizedByteBuffer)
|
||||
fbx.reset(keepingCapacity: true)
|
||||
}
|
||||
benchmark.stopMeasurement()
|
||||
}
|
||||
}
|
||||
@@ -39,14 +39,4 @@ 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"),
|
||||
]),
|
||||
])
|
||||
|
||||
@@ -654,15 +654,34 @@ class DartGenerator : public BaseGenerator {
|
||||
|
||||
std::string NamespaceAliasFromUnionType(Namespace* root_namespace,
|
||||
const Type& type) {
|
||||
const Namespace& type_namespace = *type.struct_def->defined_namespace;
|
||||
if (root_namespace->components == type_namespace.components) {
|
||||
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())) {
|
||||
return 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);
|
||||
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);
|
||||
}
|
||||
|
||||
void GenImplementationGetters(
|
||||
|
||||
@@ -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, BitwiseCopyable {
|
||||
public protocol Scalar: Equatable {
|
||||
associatedtype NumericValue
|
||||
var convertedEndian: NumericValue { get }
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
@usableFromInline
|
||||
final class Storage {
|
||||
@usableFromInline
|
||||
@frozen enum Blob: ~Copyable {
|
||||
enum Blob {
|
||||
#if !os(WASI)
|
||||
case data(Data)
|
||||
case bytes(any ContiguousBytes)
|
||||
@@ -36,40 +36,6 @@ 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.
|
||||
@@ -78,7 +44,7 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
private let capacity: Int
|
||||
/// Retained blob of data that requires the storage to retain a pointer to.
|
||||
@usableFromInline
|
||||
let retainedBlob: Blob
|
||||
var retainedBlob: Blob
|
||||
|
||||
@usableFromInline
|
||||
init(count: Int) {
|
||||
@@ -91,9 +57,9 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
init(blob: borrowing Blob, capacity count: Int) {
|
||||
init(blob: Blob, capacity count: Int) {
|
||||
capacity = count
|
||||
retainedBlob = .init(blob)
|
||||
retainedBlob = blob
|
||||
isOwned = false
|
||||
}
|
||||
|
||||
@@ -184,7 +150,6 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
|
||||
@discardableResult
|
||||
@inline(__always)
|
||||
@inlinable
|
||||
func readWithUnsafeRawPointer<T>(
|
||||
position: Int,
|
||||
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
|
||||
@@ -313,7 +278,7 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
/// - removeBytes: Removes a number of bytes from the current size
|
||||
@inline(__always)
|
||||
init(
|
||||
blob: borrowing Storage.Blob,
|
||||
blob: Storage.Blob,
|
||||
count: Int,
|
||||
removing removeBytes: Int)
|
||||
{
|
||||
@@ -353,8 +318,7 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
/// - def: Type of the object
|
||||
/// - position: the index of the object in the buffer
|
||||
@inline(__always)
|
||||
@inlinable
|
||||
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
|
||||
public func read<T>(def: T.Type, position: Int) -> T {
|
||||
_storage.readWithUnsafeRawPointer(position: position) {
|
||||
$0.bindMemory(to: T.self, capacity: 1)
|
||||
.pointee
|
||||
@@ -448,7 +412,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")
|
||||
@@ -500,9 +464,8 @@ public struct ByteBuffer: @unchecked Sendable {
|
||||
extension ByteBuffer: CustomDebugStringConvertible {
|
||||
|
||||
public var debugDescription: String {
|
||||
let blobDescription = _storage.retainedBlob.description
|
||||
return """
|
||||
buffer located at: \(blobDescription),
|
||||
"""
|
||||
buffer located at: \(_storage.retainedBlob),
|
||||
with capacity of \(capacity),
|
||||
{ writtenSize: \(_readerIndex), readerSize: \(reader),
|
||||
size: \(size) }
|
||||
|
||||
@@ -47,8 +47,7 @@ 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
|
||||
@usableFromInline
|
||||
let serializeDefaults: Bool
|
||||
private var serializeDefaults: Bool
|
||||
|
||||
/// Current alignment for the buffer
|
||||
var _minAlignment: Int = 0 {
|
||||
@@ -757,7 +756,6 @@ 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)
|
||||
@@ -796,7 +794,6 @@ 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,
|
||||
@@ -816,7 +813,6 @@ 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)
|
||||
@@ -829,7 +825,6 @@ 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
|
||||
@@ -841,8 +836,7 @@ public struct FlatBufferBuilder {
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
@inlinable
|
||||
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
|
||||
public func read<T>(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: BitwiseCopyable {}
|
||||
public protocol NativeStruct {}
|
||||
|
||||
public protocol FlatBufferVerifiableNativeStruct: NativeStruct, Verifiable {}
|
||||
|
||||
|
||||
@@ -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: BitwiseCopyable>(of type: T.Type, at o: Int32) -> T {
|
||||
public func readBuffer<T>(of type: T.Type, at o: Int32) -> T {
|
||||
bb.read(def: T.self, position: Int(o &+ position))
|
||||
}
|
||||
|
||||
|
||||
@@ -56,15 +56,8 @@ 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: byteCount.partialValue)
|
||||
try verifier.rangeInBuffer(position: start, size: intLen)
|
||||
return (start, intLen)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: BitwiseCopyable>(at position: Int) throws -> T {
|
||||
internal func getValue<T>(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
|
||||
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
|
||||
private(set) var memory: UnsafeMutableRawPointer
|
||||
|
||||
@usableFromInline
|
||||
init(count: Int, alignment: Int) {
|
||||
@@ -333,7 +333,6 @@ struct _InternalByteBuffer {
|
||||
|
||||
@discardableResult
|
||||
@inline(__always)
|
||||
@usableFromInline
|
||||
func readWithUnsafeRawPointer<T>(
|
||||
position: Int,
|
||||
_ body: (UnsafeRawPointer) throws -> T) rethrows -> T
|
||||
|
||||
@@ -27,7 +27,7 @@ public struct ByteBuffer {
|
||||
@usableFromInline
|
||||
final class Storage {
|
||||
@usableFromInline
|
||||
@frozen enum Blob: ~Copyable {
|
||||
enum Blob {
|
||||
#if !os(WASI)
|
||||
case data(Data)
|
||||
case bytes(any ContiguousBytes)
|
||||
@@ -36,23 +36,6 @@ 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.
|
||||
@@ -61,7 +44,7 @@ public struct ByteBuffer {
|
||||
private let capacity: Int
|
||||
/// Retained blob of data that requires the storage to retain a pointer to.
|
||||
@usableFromInline
|
||||
let retainedBlob: Blob
|
||||
var retainedBlob: Blob
|
||||
|
||||
@usableFromInline
|
||||
init(count: Int) {
|
||||
@@ -74,9 +57,9 @@ public struct ByteBuffer {
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
init(blob: borrowing Blob, capacity count: Int) {
|
||||
init(blob: Blob, capacity count: Int) {
|
||||
capacity = count
|
||||
retainedBlob = .init(blob)
|
||||
retainedBlob = blob
|
||||
isOwned = false
|
||||
}
|
||||
|
||||
@@ -293,7 +276,7 @@ public struct ByteBuffer {
|
||||
/// - removeBytes: Removes a number of bytes from the current size
|
||||
@inline(__always)
|
||||
init(
|
||||
blob: borrowing Storage.Blob,
|
||||
blob: Storage.Blob,
|
||||
count: Int,
|
||||
removing removeBytes: Int)
|
||||
{
|
||||
@@ -333,7 +316,7 @@ public struct ByteBuffer {
|
||||
/// - def: Type of the object
|
||||
/// - position: the index of the object in the buffer
|
||||
@inline(__always)
|
||||
public func read<T: BitwiseCopyable>(def: T.Type, position: Int) -> T {
|
||||
public func read<T>(def: T.Type, position: Int) -> T {
|
||||
_storage.readWithUnsafeRawPointer(position: position) {
|
||||
$0.bindMemory(to: T.self, capacity: 1)
|
||||
.pointee
|
||||
@@ -377,10 +360,10 @@ public struct ByteBuffer {
|
||||
@inline(__always)
|
||||
func readSizedScalar<
|
||||
T: BinaryInteger,
|
||||
T1: BinaryInteger & BitwiseCopyable,
|
||||
T2: BinaryInteger & BitwiseCopyable,
|
||||
T3: BinaryInteger & BitwiseCopyable,
|
||||
T4: BinaryInteger & BitwiseCopyable
|
||||
T1: BinaryInteger,
|
||||
T2: BinaryInteger,
|
||||
T3: BinaryInteger,
|
||||
T4: BinaryInteger
|
||||
>(
|
||||
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
|
||||
@exclusivity(unchecked) private(set) var memory: UnsafeMutableRawPointer
|
||||
var memory: UnsafeMutableRawPointer
|
||||
|
||||
@usableFromInline
|
||||
init(count: Int, alignment: Int) {
|
||||
|
||||
@@ -411,27 +411,6 @@ 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!"
|
||||
|
||||
Reference in New Issue
Block a user