[Swift] Adds new API to reduce memory copying within swift (#8484)

* Adds new API to reduce memory copying within swift

Adds new storage container _InternalByteBuffer which
will be holding the data that will be created within the swift
lib, however reading data will be redirected to ByteBuffer, which
should be able to handle all types of data that swift provide without
the need to copy the data itself. This is due to holding a reference to
the data.

Replaces assumingMemoryBinding with bindMemory which is safer

Adds function that provides access to a UnsafeBufferPointer for
scalars and NativeStructs within swift

Updates docs

Suppress compilation warnings by replacing var with let

Using overflow operators within swift to improve performance

Adds tests for GRPC message creation from a retained _InternalByteBuffer
This commit is contained in:
mustiikhalil
2025-03-18 07:48:39 +01:00
committed by GitHub
parent 1c514626e8
commit bd1b2d0baf
29 changed files with 1470 additions and 463 deletions

View File

@@ -46,11 +46,11 @@ public struct Table {
/// - Parameter o: current offset
/// - Returns: offset of field within buffer
public func offset(_ o: Int32) -> Int32 {
let vtable = position - bb.read(def: Int32.self, position: Int(position))
let vtable = position &- bb.read(def: Int32.self, position: Int(position))
return o < bb
.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(
def: Int16.self,
position: Int(vtable + o))) : 0
position: Int(vtable &+ o))) : 0
}
/// Gets the indirect offset of the current stored object
@@ -58,13 +58,13 @@ public struct Table {
/// - Parameter o: current offset
/// - Returns: offset of field within buffer
public func indirect(_ o: Int32) -> Int32 {
o + bb.read(def: Int32.self, position: Int(o))
o &+ bb.read(def: Int32.self, position: Int(o))
}
/// String reads from the buffer with respect to position of the current table.
/// - Parameter offset: Offset of the string
public func string(at offset: Int32) -> String? {
directString(at: offset + position)
directString(at: offset &+ position)
}
/// Direct string reads from the buffer disregarding the position of the table.
@@ -73,9 +73,9 @@ public struct Table {
/// - Parameter offset: Offset of the string
public func directString(at offset: Int32) -> String? {
var offset = offset
offset += bb.read(def: Int32.self, position: Int(offset))
offset &+= bb.read(def: Int32.self, position: Int(offset))
let count = bb.read(def: Int32.self, position: Int(offset))
let position = Int(offset) + MemoryLayout<Int32>.size
let position = Int(offset) &+ MemoryLayout<Int32>.size
return bb.readString(at: position, count: Int(count))
}
@@ -84,7 +84,7 @@ public struct Table {
/// - 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 {
directRead(of: T.self, offset: o + position)
directRead(of: T.self, offset: o &+ position)
}
/// Reads from the buffer disregarding the position of the table.
@@ -101,8 +101,7 @@ public struct Table {
/// - type: Type of Element that needs to be read from the buffer
/// - o: Offset of the Element
public func directRead<T>(of type: T.Type, offset o: Int32) -> T {
let r = bb.read(def: T.self, position: Int(o))
return r
bb.read(def: T.self, position: Int(o))
}
/// Returns that current `Union` object at a specific offset
@@ -110,7 +109,7 @@ public struct Table {
/// - Parameter o: offset
/// - Returns: A flatbuffers object
public func union<T: FlatbuffersInitializable>(_ o: Int32) -> T {
let o = o + position
let o = o &+ position
return directUnion(o)
}
@@ -118,7 +117,7 @@ public struct Table {
/// - Parameter o: offset
/// - Returns: A flatbuffers object
public func directUnion<T: FlatbuffersInitializable>(_ o: Int32) -> T {
T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
T.init(bb, o: o &+ bb.read(def: Int32.self, position: Int(o)))
}
/// Returns a vector of type T at a specific offset
@@ -131,13 +130,30 @@ public struct Table {
return bb.readSlice(index: Int(vector(at: o)), count: Int(vector(count: o)))
}
/// Returns the underlying pointer to a vector within the buffer
/// This should only be used by `Scalars`
/// - Parameter off: Readable offset
/// - Returns: Returns a pointer to the underlying data
@inline(__always)
public func withUnsafePointerToSlice<T>(
at off: Int32,
body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T?
{
let o = offset(off)
guard o != 0 else { return nil }
return try bb.withUnsafePointerToSlice(
index: Int(vector(at: o)),
count: Int(vector(count: o)),
body: body)
}
/// Vector count gets the count of Elements within the array
/// - Parameter o: start offset of the vector
/// - returns: Count of elements
public func vector(count o: Int32) -> Int32 {
var o = o
o += position
o += bb.read(def: Int32.self, position: Int(o))
o &+= position
o &+= bb.read(def: Int32.self, position: Int(o))
return bb.read(def: Int32.self, position: Int(o))
}
@@ -146,8 +162,8 @@ public struct Table {
/// - returns: the start index of the vector
public func vector(at o: Int32) -> Int32 {
var o = o
o += position
return o + bb.read(def: Int32.self, position: Int(o)) + 4
o &+= position
return o &+ bb.read(def: Int32.self, position: Int(o)) + 4
}
/// Reading an indirect offset of a table.
@@ -165,15 +181,16 @@ public struct Table {
/// - vOffset: Field offset within a vtable
/// - fbb: ByteBuffer
/// - Returns: an position of a field
@inline(__always)
static public func offset(
_ o: Int32,
vOffset: Int32,
fbb: ByteBuffer) -> Int32
fbb: inout FlatBufferBuilder) -> Int32
{
let vTable = Int32(fbb.capacity) - o
return vTable + Int32(fbb.read(
let vTable = Int32(fbb.capacity) &- o
return vTable &+ Int32(fbb.read(
def: Int16.self,
position: Int(vTable + vOffset - fbb.read(
position: Int(vTable &+ vOffset &- fbb.read(
def: Int32.self,
position: Int(vTable)))))
}
@@ -184,27 +201,28 @@ public struct Table {
/// - off2: second offset to compare
/// - fbb: Bytebuffer
/// - Returns: returns the difference between
@inline(__always)
static public func compare(
_ off1: Int32,
_ off2: Int32,
fbb: ByteBuffer) -> Int32
fbb: inout FlatBufferBuilder) -> Int32
{
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
let _off2 = off2 + fbb.read(def: Int32.self, position: Int(off2))
let _off1 = off1 &+ fbb.read(def: Int32.self, position: Int(off1))
let _off2 = off2 &+ fbb.read(def: Int32.self, position: Int(off2))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = fbb.read(def: Int32.self, position: Int(_off2))
let startPos1 = _off1 + memorySize
let startPos2 = _off2 + memorySize
let startPos1 = _off1 &+ memorySize
let startPos2 = _off2 &+ memorySize
let minValue = min(len1, len2)
for i in 0...minValue {
let b1 = fbb.read(def: Int8.self, position: Int(i + startPos1))
let b2 = fbb.read(def: Int8.self, position: Int(i + startPos2))
let b1 = fbb.read(def: Int8.self, position: Int(i &+ startPos1))
let b2 = fbb.read(def: Int8.self, position: Int(i &+ startPos2))
if b1 != b2 {
return Int32(b2 - b1)
return Int32(b2 &- b1)
}
}
return len1 - len2
return len1 &- len2
}
/// Compares two objects at offset A and array of `Bytes` within a ByteBuffer
@@ -213,24 +231,103 @@ public struct Table {
/// - key: bytes array to compare to
/// - fbb: Bytebuffer
/// - Returns: returns the difference between
@inline(__always)
static public func compare(
_ off1: Int32,
_ key: [Byte],
fbb: inout FlatBufferBuilder) -> Int32
{
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 &+ fbb.read(def: Int32.self, position: Int(off1))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = Int32(key.count)
let startPos1 = _off1 &+ memorySize
let minValue = min(len1, len2)
for i in 0..<minValue {
let b = fbb.read(def: Int8.self, position: Int(i &+ startPos1))
let byte = key[Int(i)]
if b != byte {
return Int32(b &- Int8(byte))
}
}
return len1 &- len2
}
/// Gets a vtable value according to an table Offset and a field offset
/// - Parameters:
/// - o: offset relative to entire buffer
/// - vOffset: Field offset within a vtable
/// - fbb: ByteBuffer
/// - Returns: an position of a field
@inline(__always)
static public func offset(
_ o: Int32,
vOffset: Int32,
fbb: ByteBuffer) -> Int32
{
let vTable = Int32(fbb.capacity) &- o
return vTable &+ Int32(fbb.read(
def: Int16.self,
position: Int(vTable &+ vOffset &- fbb.read(
def: Int32.self,
position: Int(vTable)))))
}
/// Compares two objects at offset A and offset B within a ByteBuffer
/// - Parameters:
/// - off1: first offset to compare
/// - off2: second offset to compare
/// - fbb: Bytebuffer
/// - Returns: returns the difference between
@inline(__always)
static public func compare(
_ off1: Int32,
_ off2: Int32,
fbb: ByteBuffer) -> Int32
{
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 &+ fbb.read(def: Int32.self, position: Int(off1))
let _off2 = off2 &+ fbb.read(def: Int32.self, position: Int(off2))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = fbb.read(def: Int32.self, position: Int(_off2))
let startPos1 = _off1 &+ memorySize
let startPos2 = _off2 &+ memorySize
let minValue = min(len1, len2)
for i in 0...minValue {
let b1 = fbb.read(def: Int8.self, position: Int(i &+ startPos1))
let b2 = fbb.read(def: Int8.self, position: Int(i &+ startPos2))
if b1 != b2 {
return Int32(b2 &- b1)
}
}
return len1 &- len2
}
/// Compares two objects at offset A and array of `Bytes` within a ByteBuffer
/// - Parameters:
/// - off1: Offset to compare to
/// - key: bytes array to compare to
/// - fbb: Bytebuffer
/// - Returns: returns the difference between
@inline(__always)
static public func compare(
_ off1: Int32,
_ key: [Byte],
fbb: ByteBuffer) -> Int32
{
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
let _off1 = off1 &+ fbb.read(def: Int32.self, position: Int(off1))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = Int32(key.count)
let startPos1 = _off1 + memorySize
let startPos1 = _off1 &+ memorySize
let minValue = min(len1, len2)
for i in 0..<minValue {
let b = fbb.read(def: Int8.self, position: Int(i + startPos1))
let b = fbb.read(def: Int8.self, position: Int(i &+ startPos1))
let byte = key[Int(i)]
if b != byte {
return Int32(b - Int8(byte))
return Int32(b &- Int8(byte))
}
}
return len1 - len2
return len1 &- len2
}
}