mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-24 21:56:10 +00:00
[Swift] Push contiguous bytes (#8157)
* Add version of push which takes ContiguousBytes * Ensure overloads aren't ambiguous * Add version of createVector * Add version of push which takes ContiguousBytes * Ensure overloads aren't ambiguous * Add version of createVector * Add similar conditional to other use of ContiguousBytes * Attempt CI fix * Use memcpy instead of copyMemory memcpy is faster in tests * Add testContiguousBytes * Add benchmarks * Add version of createVector * Add benchmarks * Update push to copy memory Since we don't care about endianness, we can simply memcpy the array of scalars * Remove function and benchmarks Since we don't care about endianness, a FixedWidthInteger version of createVector isn't needed * Improve naming * Add doc comment
This commit is contained in:
@@ -228,13 +228,33 @@ public struct ByteBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
mutating func push<T: Scalar>(elements: [T]) {
|
mutating func push<T: Scalar>(elements: [T]) {
|
||||||
let size = elements.count &* MemoryLayout<T>.size
|
elements.withUnsafeBytes { ptr in
|
||||||
ensureSpace(size: size)
|
ensureSpace(size: ptr.count)
|
||||||
elements.reversed().forEach { s in
|
memcpy(
|
||||||
push(value: s, len: MemoryLayout.size(ofValue: s))
|
_storage.memory.advanced(by: writerIndex &- ptr.count),
|
||||||
|
UnsafeRawPointer(ptr.baseAddress!),
|
||||||
|
ptr.count)
|
||||||
|
self._writerSize = self._writerSize &+ ptr.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a `ContiguousBytes` to buffer memory
|
||||||
|
/// - Parameter value: bytes to copy
|
||||||
|
#if swift(>=5.0) && !os(WASI)
|
||||||
|
@inline(__always)
|
||||||
|
@usableFromInline
|
||||||
|
mutating func push(bytes: ContiguousBytes) {
|
||||||
|
bytes.withUnsafeBytes { ptr in
|
||||||
|
ensureSpace(size: ptr.count)
|
||||||
|
memcpy(
|
||||||
|
_storage.memory.advanced(by: writerIndex &- ptr.count),
|
||||||
|
UnsafeRawPointer(ptr.baseAddress!),
|
||||||
|
ptr.count)
|
||||||
|
self._writerSize = self._writerSize &+ ptr.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Adds an object of type NativeStruct into the buffer
|
/// Adds an object of type NativeStruct into the buffer
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - value: Object that will be written to the buffer
|
/// - value: Object that will be written to the buffer
|
||||||
|
|||||||
@@ -473,6 +473,22 @@ public struct FlatBufferBuilder {
|
|||||||
return endVector(len: size)
|
return endVector(len: size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if swift(>=5.0) && !os(WASI)
|
||||||
|
@inline(__always)
|
||||||
|
/// Creates a vector of bytes in the buffer.
|
||||||
|
///
|
||||||
|
/// Allows creating a vector from `Data` without copying to a `[UInt8]`
|
||||||
|
///
|
||||||
|
/// - Parameter bytes: bytes to be written into the buffer
|
||||||
|
/// - Returns: ``Offset`` of the vector
|
||||||
|
mutating public func createVector(bytes: ContiguousBytes) -> Offset {
|
||||||
|
let size = bytes.withUnsafeBytes { ptr in ptr.count }
|
||||||
|
startVector(size, elementSize: MemoryLayout<UInt8>.size)
|
||||||
|
_bb.push(bytes: bytes)
|
||||||
|
return endVector(len: size)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Creates a vector of type ``Enum`` into the ``ByteBuffer``
|
/// Creates a vector of type ``Enum`` into the ``ByteBuffer``
|
||||||
///
|
///
|
||||||
/// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
|
/// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
|
||||||
|
|||||||
@@ -32,6 +32,20 @@ benchmark("100Strings") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
benchmark("100Bytes") {
|
||||||
|
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
||||||
|
for _ in 0..<1_000_000 {
|
||||||
|
_ = fb.createVector(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmark("100Bytes-ContiguousBytes") {
|
||||||
|
var fb = FlatBufferBuilder(initialSize: 1<<20)
|
||||||
|
for _ in 0..<1_000_000 {
|
||||||
|
_ = fb.createVector(bytes: bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
benchmark("FlatBufferBuilder.add") {
|
benchmark("FlatBufferBuilder.add") {
|
||||||
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
|
var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32)
|
||||||
for _ in 0..<1_000_000 {
|
for _ in 0..<1_000_000 {
|
||||||
@@ -73,6 +87,7 @@ benchmark("structs") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let str = (0...99).map { _ -> String in "x" }.joined()
|
let str = (0...99).map { _ -> String in "x" }.joined()
|
||||||
|
let bytes: [UInt8] = Array(repeating: 42, count: 100)
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
struct AA: NativeStruct {
|
struct AA: NativeStruct {
|
||||||
|
|||||||
@@ -484,4 +484,21 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testContiguousBytes() {
|
||||||
|
let byteArray: [UInt8] = [3, 1, 4, 1, 5, 9]
|
||||||
|
var fbb = FlatBufferBuilder(initialSize: 1)
|
||||||
|
let name = fbb.create(string: "Frodo")
|
||||||
|
let bytes = fbb.createVector(bytes: byteArray)
|
||||||
|
let root = Monster.createMonster(
|
||||||
|
&fbb,
|
||||||
|
nameOffset: name,
|
||||||
|
inventoryVectorOffset: bytes)
|
||||||
|
fbb.finish(offset: root)
|
||||||
|
var buffer = fbb.sizedBuffer
|
||||||
|
let monster: Monster = getRoot(byteBuffer: &buffer)
|
||||||
|
let values = monster.inventory
|
||||||
|
|
||||||
|
XCTAssertEqual(byteArray, values)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user