mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-28 17:30:00 +00:00
[Swift] Moves capacity outside of Storage (#8650)
- Cleans up capacity usage within the lib and moves it outside of the Storage - Use overflow operators
This commit is contained in:
@@ -40,11 +40,11 @@ public struct ByteBuffer {
|
|||||||
|
|
||||||
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
|
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
|
||||||
private let isOwned: Bool
|
private let isOwned: Bool
|
||||||
|
/// Capacity of UInt8 the buffer can hold
|
||||||
|
private let capacity: Int
|
||||||
/// Retained blob of data that requires the storage to retain a pointer to.
|
/// Retained blob of data that requires the storage to retain a pointer to.
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
var retainedBlob: Blob
|
var retainedBlob: Blob
|
||||||
/// Capacity of UInt8 the buffer can hold
|
|
||||||
var capacity: Int
|
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
init(count: Int) {
|
init(count: Int) {
|
||||||
@@ -179,11 +179,11 @@ public struct ByteBuffer {
|
|||||||
/// The size of the elements written to the buffer + their paddings
|
/// The size of the elements written to the buffer + their paddings
|
||||||
private var _readerIndex: Int = 0
|
private var _readerIndex: Int = 0
|
||||||
/// Reader is the position of the current Writer Index (capacity - size)
|
/// Reader is the position of the current Writer Index (capacity - size)
|
||||||
public var reader: Int { _storage.capacity &- _readerIndex }
|
public var reader: Int { capacity &- _readerIndex }
|
||||||
/// Current size of the buffer
|
/// Current size of the buffer
|
||||||
public var size: UOffset { UOffset(_readerIndex) }
|
public var size: UOffset { UOffset(_readerIndex) }
|
||||||
/// Current capacity for the buffer
|
/// Current capacity for the buffer
|
||||||
public var capacity: Int { _storage.capacity }
|
public let capacity: Int
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from an InternalByteBuffer
|
/// Constructor that creates a Flatbuffer object from an InternalByteBuffer
|
||||||
/// - Parameter
|
/// - Parameter
|
||||||
@@ -194,6 +194,7 @@ public struct ByteBuffer {
|
|||||||
blob: .byteBuffer(byteBuffer),
|
blob: .byteBuffer(byteBuffer),
|
||||||
capacity: byteBuffer.capacity)
|
capacity: byteBuffer.capacity)
|
||||||
_readerIndex = Int(byteBuffer.size)
|
_readerIndex = Int(byteBuffer.size)
|
||||||
|
self.capacity = byteBuffer.capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer from unsafe memory region by copying
|
/// Constructor that creates a Flatbuffer from unsafe memory region by copying
|
||||||
@@ -209,7 +210,8 @@ public struct ByteBuffer {
|
|||||||
{
|
{
|
||||||
_storage = Storage(count: capacity)
|
_storage = Storage(count: capacity)
|
||||||
_storage.copy(from: memory, count: capacity)
|
_storage.copy(from: memory, count: capacity)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = capacity
|
||||||
|
self.capacity = capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from a UInt8
|
/// Constructor that creates a Flatbuffer object from a UInt8
|
||||||
@@ -218,7 +220,8 @@ public struct ByteBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
public init(bytes: [UInt8]) {
|
public init(bytes: [UInt8]) {
|
||||||
_storage = Storage(blob: .array(bytes), capacity: bytes.count)
|
_storage = Storage(blob: .array(bytes), capacity: bytes.count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = bytes.count
|
||||||
|
capacity = bytes.count
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !os(WASI)
|
#if !os(WASI)
|
||||||
@@ -228,7 +231,8 @@ public struct ByteBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
public init(data: Data) {
|
public init(data: Data) {
|
||||||
_storage = Storage(blob: .data(data), capacity: data.count)
|
_storage = Storage(blob: .data(data), capacity: data.count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = data.count
|
||||||
|
capacity = data.count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from a ContiguousBytes
|
/// Constructor that creates a Flatbuffer object from a ContiguousBytes
|
||||||
@@ -241,7 +245,8 @@ public struct ByteBuffer {
|
|||||||
count: Int)
|
count: Int)
|
||||||
{
|
{
|
||||||
_storage = Storage(blob: .bytes(contiguousBytes), capacity: count)
|
_storage = Storage(blob: .bytes(contiguousBytes), capacity: count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = count
|
||||||
|
self.capacity = count
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -259,7 +264,8 @@ public struct ByteBuffer {
|
|||||||
_storage = Storage(
|
_storage = Storage(
|
||||||
blob: .pointer(memory),
|
blob: .pointer(memory),
|
||||||
capacity: capacity)
|
capacity: capacity)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = capacity
|
||||||
|
self.capacity = capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a copy of the existing flatbuffer, by copying it to a different memory.
|
/// Creates a copy of the existing flatbuffer, by copying it to a different memory.
|
||||||
@@ -275,6 +281,7 @@ public struct ByteBuffer {
|
|||||||
{
|
{
|
||||||
_storage = Storage(blob: blob, capacity: count)
|
_storage = Storage(blob: blob, capacity: count)
|
||||||
_readerIndex = removeBytes
|
_readerIndex = removeBytes
|
||||||
|
capacity = count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write stores an object into the buffer directly or indirectly.
|
/// Write stores an object into the buffer directly or indirectly.
|
||||||
@@ -289,11 +296,11 @@ public struct ByteBuffer {
|
|||||||
func write<T>(value: T, index: Int, direct: Bool = false) {
|
func write<T>(value: T, index: Int, direct: Bool = false) {
|
||||||
var index = index
|
var index = index
|
||||||
if !direct {
|
if !direct {
|
||||||
index = _storage.capacity &- index
|
index = capacity &- index
|
||||||
}
|
}
|
||||||
assert(index < _storage.capacity, "Write index is out of writing bound")
|
assert(index < capacity, "Write index is out of writing bound")
|
||||||
assert(index >= 0, "Writer index should be above zero")
|
assert(index >= 0, "Writer index should be above zero")
|
||||||
withUnsafePointer(to: value) { ptr in
|
_ = withUnsafePointer(to: value) { ptr in
|
||||||
_storage.withUnsafeRawPointer {
|
_storage.withUnsafeRawPointer {
|
||||||
memcpy(
|
memcpy(
|
||||||
$0.advanced(by: index),
|
$0.advanced(by: index),
|
||||||
@@ -325,7 +332,7 @@ public struct ByteBuffer {
|
|||||||
count: Int) -> [T]
|
count: Int) -> [T]
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
|
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
@@ -348,7 +355,7 @@ public struct ByteBuffer {
|
|||||||
body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T
|
body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return try _storage.readWithUnsafeRawPointer(position: index) {
|
return try _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
try body(UnsafeRawBufferPointer(start: $0, count: count))
|
try body(UnsafeRawBufferPointer(start: $0, count: count))
|
||||||
@@ -368,7 +375,7 @@ public struct ByteBuffer {
|
|||||||
type: String.Encoding = .utf8) -> String?
|
type: String.Encoding = .utf8) -> String?
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
let buf = UnsafeBufferPointer(
|
let buf = UnsafeBufferPointer(
|
||||||
@@ -390,7 +397,7 @@ public struct ByteBuffer {
|
|||||||
count: Int) -> String?
|
count: Int) -> String?
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
String(cString: $0.bindMemory(to: UInt8.self, capacity: count))
|
String(cString: $0.bindMemory(to: UInt8.self, capacity: count))
|
||||||
@@ -404,11 +411,11 @@ public struct ByteBuffer {
|
|||||||
public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
|
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(
|
assert(
|
||||||
removeBytes < _storage.capacity,
|
removeBytes < capacity,
|
||||||
"Can NOT remove more bytes than the ones allocated")
|
"Can NOT remove more bytes than the ones allocated")
|
||||||
return ByteBuffer(
|
return ByteBuffer(
|
||||||
blob: _storage.retainedBlob,
|
blob: _storage.retainedBlob,
|
||||||
count: _storage.capacity,
|
count: capacity,
|
||||||
removing: _readerIndex &- removeBytes)
|
removing: _readerIndex &- removeBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +463,7 @@ extension ByteBuffer: CustomDebugStringConvertible {
|
|||||||
public var debugDescription: String {
|
public var debugDescription: String {
|
||||||
"""
|
"""
|
||||||
buffer located at: \(_storage.retainedBlob),
|
buffer located at: \(_storage.retainedBlob),
|
||||||
with capacity of \(_storage.capacity),
|
with capacity of \(capacity),
|
||||||
{ writtenSize: \(_readerIndex), readerSize: \(reader),
|
{ writtenSize: \(_readerIndex), readerSize: \(reader),
|
||||||
size: \(size) }
|
size: \(size) }
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ extension Mutable where Self == Table {
|
|||||||
/// - index: index of the Element
|
/// - index: index of the Element
|
||||||
public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
|
public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
|
||||||
guard index != 0 else { return false }
|
guard index != 0 else { return false }
|
||||||
return mutate(value: value, o: index + position)
|
return mutate(value: value, o: index &+ position)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Directly mutates the element by calling mutate
|
/// Directly mutates the element by calling mutate
|
||||||
@@ -70,7 +70,7 @@ extension Mutable where Self == Struct {
|
|||||||
/// - value: New value to be inserted to the buffer
|
/// - value: New value to be inserted to the buffer
|
||||||
/// - index: index of the Element
|
/// - index: index of the Element
|
||||||
public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
|
public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
|
||||||
mutate(value: value, o: index + position)
|
mutate(value: value, o: index &+ position)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Directly mutates the element by calling mutate
|
/// Directly mutates the element by calling mutate
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public struct Struct {
|
|||||||
/// - o: Current offset of the data
|
/// - o: Current offset of the data
|
||||||
/// - Returns: Data of Type T that conforms to type Scalar
|
/// - Returns: Data of Type T that conforms to type Scalar
|
||||||
public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
|
public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
|
||||||
let r = bb.read(def: T.self, position: Int(o + position))
|
let r = bb.read(def: T.self, position: Int(o &+ position))
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ public struct Table {
|
|||||||
public func vector(at o: Int32) -> Int32 {
|
public func vector(at o: Int32) -> Int32 {
|
||||||
var o = o
|
var o = o
|
||||||
o &+= position
|
o &+= position
|
||||||
return o &+ bb.read(def: Int32.self, position: Int(o)) + 4
|
return o &+ bb.read(def: Int32.self, position: Int(o)) &+ 4
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reading an indirect offset of a table.
|
/// Reading an indirect offset of a table.
|
||||||
@@ -176,7 +176,7 @@ public struct Table {
|
|||||||
/// - fbb: ByteBuffer
|
/// - fbb: ByteBuffer
|
||||||
/// - Returns: table offset
|
/// - Returns: table offset
|
||||||
static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 {
|
static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 {
|
||||||
o + fbb.read(def: Int32.self, position: Int(o))
|
o &+ fbb.read(def: Int32.self, position: Int(o))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a vtable value according to an table Offset and a field offset
|
/// Gets a vtable value according to an table Offset and a field offset
|
||||||
|
|||||||
@@ -31,15 +31,12 @@ struct _InternalByteBuffer {
|
|||||||
final class Storage {
|
final class Storage {
|
||||||
/// pointer to the start of the buffer object in memory
|
/// pointer to the start of the buffer object in memory
|
||||||
private(set) var memory: UnsafeMutableRawPointer
|
private(set) var memory: UnsafeMutableRawPointer
|
||||||
/// Capacity of UInt8 the buffer can hold
|
|
||||||
private(set) var capacity: Int
|
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
init(count: Int, alignment: Int) {
|
init(count: Int, alignment: Int) {
|
||||||
memory = UnsafeMutableRawPointer.allocate(
|
memory = UnsafeMutableRawPointer.allocate(
|
||||||
byteCount: count,
|
byteCount: count,
|
||||||
alignment: alignment)
|
alignment: alignment)
|
||||||
capacity = count
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@@ -54,15 +51,12 @@ struct _InternalByteBuffer {
|
|||||||
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
|
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
|
||||||
/// - Parameter size: Size of the current object
|
/// - Parameter size: Size of the current object
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
|
func reallocate(
|
||||||
let currentWritingIndex = capacity &- writerSize
|
capacity: Int,
|
||||||
while capacity <= writerSize &+ size {
|
writerSize: Int,
|
||||||
capacity = capacity << 1
|
currentWritingIndex: Int,
|
||||||
}
|
alignment: Int
|
||||||
|
) {
|
||||||
/// solution take from Apple-NIO
|
|
||||||
capacity = capacity.convertToPowerofTwo
|
|
||||||
|
|
||||||
let newData = UnsafeMutableRawPointer.allocate(
|
let newData = UnsafeMutableRawPointer.allocate(
|
||||||
byteCount: capacity,
|
byteCount: capacity,
|
||||||
alignment: alignment)
|
alignment: alignment)
|
||||||
@@ -84,7 +78,7 @@ struct _InternalByteBuffer {
|
|||||||
/// Alignment of the current memory being written to the buffer
|
/// Alignment of the current memory being written to the buffer
|
||||||
var alignment = 1
|
var alignment = 1
|
||||||
/// Current Index which is being used to write to the buffer, it is written from the end to the start of the buffer
|
/// Current Index which is being used to write to the buffer, it is written from the end to the start of the buffer
|
||||||
var writerIndex: Int { _storage.capacity &- _writerSize }
|
var writerIndex: Int { capacity &- _writerSize }
|
||||||
|
|
||||||
/// Reader is the position of the current Writer Index (capacity - size)
|
/// Reader is the position of the current Writer Index (capacity - size)
|
||||||
public var reader: Int { writerIndex }
|
public var reader: Int { writerIndex }
|
||||||
@@ -94,7 +88,7 @@ struct _InternalByteBuffer {
|
|||||||
@usableFromInline
|
@usableFromInline
|
||||||
var memory: UnsafeMutableRawPointer { _storage.memory }
|
var memory: UnsafeMutableRawPointer { _storage.memory }
|
||||||
/// Current capacity for the buffer
|
/// Current capacity for the buffer
|
||||||
public var capacity: Int { _storage.capacity }
|
public private(set) var capacity: Int
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer instance with a size
|
/// Constructor that creates a Flatbuffer instance with a size
|
||||||
/// - Parameter:
|
/// - Parameter:
|
||||||
@@ -102,6 +96,7 @@ struct _InternalByteBuffer {
|
|||||||
/// - allowReadingUnalignedBuffers: allow reading from unaligned buffer
|
/// - allowReadingUnalignedBuffers: allow reading from unaligned buffer
|
||||||
init(initialSize size: Int) {
|
init(initialSize size: Int) {
|
||||||
initialSize = size.convertToPowerofTwo
|
initialSize = size.convertToPowerofTwo
|
||||||
|
capacity = initialSize
|
||||||
_storage = Storage(count: initialSize, alignment: alignment)
|
_storage = Storage(count: initialSize, alignment: alignment)
|
||||||
_storage.initialize(for: initialSize)
|
_storage.initialize(for: initialSize)
|
||||||
}
|
}
|
||||||
@@ -246,11 +241,11 @@ struct _InternalByteBuffer {
|
|||||||
func write<T>(value: T, index: Int, direct: Bool = false) {
|
func write<T>(value: T, index: Int, direct: Bool = false) {
|
||||||
var index = index
|
var index = index
|
||||||
if !direct {
|
if !direct {
|
||||||
index = _storage.capacity &- index
|
index = capacity &- index
|
||||||
}
|
}
|
||||||
assert(index < _storage.capacity, "Write index is out of writing bound")
|
assert(index < capacity, "Write index is out of writing bound")
|
||||||
assert(index >= 0, "Writer index should be above zero")
|
assert(index >= 0, "Writer index should be above zero")
|
||||||
withUnsafePointer(to: value) {
|
_ = withUnsafePointer(to: value) {
|
||||||
memcpy(
|
memcpy(
|
||||||
_storage.memory.advanced(by: index),
|
_storage.memory.advanced(by: index),
|
||||||
$0,
|
$0,
|
||||||
@@ -262,10 +257,24 @@ struct _InternalByteBuffer {
|
|||||||
/// - Parameter size: size of object
|
/// - Parameter size: size of object
|
||||||
@discardableResult
|
@discardableResult
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
@inline(__always)
|
|
||||||
mutating func ensureSpace(size: Int) -> Int {
|
mutating func ensureSpace(size: Int) -> Int {
|
||||||
if size &+ _writerSize > _storage.capacity {
|
let expectedWriterIndex = size &+ _writerSize
|
||||||
_storage.reallocate(size, writerSize: _writerSize, alignment: alignment)
|
if expectedWriterIndex > capacity {
|
||||||
|
|
||||||
|
let currentWritingIndex = capacity &- _writerSize
|
||||||
|
while capacity <= expectedWriterIndex {
|
||||||
|
capacity = capacity << 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// solution take from Apple-NIO
|
||||||
|
capacity = capacity.convertToPowerofTwo
|
||||||
|
|
||||||
|
|
||||||
|
_storage.reallocate(
|
||||||
|
capacity: capacity,
|
||||||
|
writerSize: _writerSize,
|
||||||
|
currentWritingIndex: currentWritingIndex,
|
||||||
|
alignment: alignment)
|
||||||
}
|
}
|
||||||
assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
|
assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
|
||||||
return size
|
return size
|
||||||
@@ -295,8 +304,9 @@ struct _InternalByteBuffer {
|
|||||||
_writerSize = 0
|
_writerSize = 0
|
||||||
alignment = 1
|
alignment = 1
|
||||||
if keepingCapacity {
|
if keepingCapacity {
|
||||||
_storage.initialize(for: _storage.capacity)
|
_storage.initialize(for: capacity)
|
||||||
} else {
|
} else {
|
||||||
|
capacity = initialSize
|
||||||
_storage = Storage(count: initialSize, alignment: alignment)
|
_storage = Storage(count: initialSize, alignment: alignment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,7 +368,7 @@ extension _InternalByteBuffer: CustomDebugStringConvertible {
|
|||||||
|
|
||||||
public var debugDescription: String {
|
public var debugDescription: String {
|
||||||
"""
|
"""
|
||||||
buffer located at: \(_storage.memory), with capacity of \(_storage.capacity)
|
buffer located at: \(_storage.memory), with capacity of \(capacity)
|
||||||
{ writerSize: \(_writerSize), readerSize: \(reader), writerIndex: \(
|
{ writerSize: \(_writerSize), readerSize: \(reader), writerIndex: \(
|
||||||
writerIndex) }
|
writerIndex) }
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ public struct ByteBuffer {
|
|||||||
|
|
||||||
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
|
/// This storage doesn't own the memory, therefore, we won't deallocate on deinit.
|
||||||
private let isOwned: Bool
|
private let isOwned: Bool
|
||||||
|
/// Capacity of UInt8 the buffer can hold
|
||||||
|
private let capacity: Int
|
||||||
/// Retained blob of data that requires the storage to retain a pointer to.
|
/// Retained blob of data that requires the storage to retain a pointer to.
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
var retainedBlob: Blob
|
var retainedBlob: Blob
|
||||||
/// Capacity of UInt8 the buffer can hold
|
|
||||||
var capacity: Int
|
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
init(count: Int) {
|
init(count: Int) {
|
||||||
@@ -178,12 +178,10 @@ public struct ByteBuffer {
|
|||||||
|
|
||||||
/// The size of the elements written to the buffer + their paddings
|
/// The size of the elements written to the buffer + their paddings
|
||||||
private var _readerIndex: Int = 0
|
private var _readerIndex: Int = 0
|
||||||
// /// Reader is the position of the current Writer Index (capacity - size)
|
|
||||||
// var reader: Int { _storage.capacity &- _readerIndex }
|
|
||||||
/// Current size of the buffer
|
/// Current size of the buffer
|
||||||
public var count: Int { _readerIndex }
|
public var count: Int { _readerIndex }
|
||||||
/// Current capacity for the buffer including unused space
|
/// Current capacity for the buffer including unused space
|
||||||
public var capacity: Int { _storage.capacity }
|
public let capacity: Int
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from an InternalByteBuffer
|
/// Constructor that creates a Flatbuffer object from an InternalByteBuffer
|
||||||
/// - Parameter
|
/// - Parameter
|
||||||
@@ -194,6 +192,7 @@ public struct ByteBuffer {
|
|||||||
blob: .byteBuffer(byteBuffer),
|
blob: .byteBuffer(byteBuffer),
|
||||||
capacity: byteBuffer.capacity)
|
capacity: byteBuffer.capacity)
|
||||||
_readerIndex = byteBuffer.writerIndex
|
_readerIndex = byteBuffer.writerIndex
|
||||||
|
capacity = byteBuffer.capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer from unsafe memory region by copying
|
/// Constructor that creates a Flatbuffer from unsafe memory region by copying
|
||||||
@@ -209,7 +208,8 @@ public struct ByteBuffer {
|
|||||||
{
|
{
|
||||||
_storage = Storage(count: capacity)
|
_storage = Storage(count: capacity)
|
||||||
_storage.copy(from: memory, count: capacity)
|
_storage.copy(from: memory, count: capacity)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = capacity
|
||||||
|
self.capacity = capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from a UInt8
|
/// Constructor that creates a Flatbuffer object from a UInt8
|
||||||
@@ -218,7 +218,8 @@ public struct ByteBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
public init(bytes: [UInt8]) {
|
public init(bytes: [UInt8]) {
|
||||||
_storage = Storage(blob: .array(bytes), capacity: bytes.count)
|
_storage = Storage(blob: .array(bytes), capacity: bytes.count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = bytes.count
|
||||||
|
capacity = bytes.count
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !os(WASI)
|
#if !os(WASI)
|
||||||
@@ -228,7 +229,8 @@ public struct ByteBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
public init(data: Data) {
|
public init(data: Data) {
|
||||||
_storage = Storage(blob: .data(data), capacity: data.count)
|
_storage = Storage(blob: .data(data), capacity: data.count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = data.count
|
||||||
|
capacity = data.count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that creates a Flatbuffer object from a ContiguousBytes
|
/// Constructor that creates a Flatbuffer object from a ContiguousBytes
|
||||||
@@ -241,7 +243,8 @@ public struct ByteBuffer {
|
|||||||
count: Int)
|
count: Int)
|
||||||
{
|
{
|
||||||
_storage = Storage(blob: .bytes(contiguousBytes), capacity: count)
|
_storage = Storage(blob: .bytes(contiguousBytes), capacity: count)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = count
|
||||||
|
capacity = count
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -259,7 +262,8 @@ public struct ByteBuffer {
|
|||||||
_storage = Storage(
|
_storage = Storage(
|
||||||
blob: .pointer(memory),
|
blob: .pointer(memory),
|
||||||
capacity: capacity)
|
capacity: capacity)
|
||||||
_readerIndex = _storage.capacity
|
_readerIndex = capacity
|
||||||
|
self.capacity = capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a copy of the existing flatbuffer, by copying it to a different memory.
|
/// Creates a copy of the existing flatbuffer, by copying it to a different memory.
|
||||||
@@ -275,6 +279,7 @@ public struct ByteBuffer {
|
|||||||
{
|
{
|
||||||
_storage = Storage(blob: blob, capacity: count)
|
_storage = Storage(blob: blob, capacity: count)
|
||||||
_readerIndex = removeBytes
|
_readerIndex = removeBytes
|
||||||
|
capacity = count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write stores an object into the buffer directly or indirectly.
|
/// Write stores an object into the buffer directly or indirectly.
|
||||||
@@ -289,11 +294,11 @@ public struct ByteBuffer {
|
|||||||
func write<T>(value: T, index: Int, direct: Bool = false) {
|
func write<T>(value: T, index: Int, direct: Bool = false) {
|
||||||
var index = index
|
var index = index
|
||||||
if !direct {
|
if !direct {
|
||||||
index = _storage.capacity &- index
|
index = capacity &- index
|
||||||
}
|
}
|
||||||
assert(index < _storage.capacity, "Write index is out of writing bound")
|
assert(index < capacity, "Write index is out of writing bound")
|
||||||
assert(index >= 0, "Writer index should be above zero")
|
assert(index >= 0, "Writer index should be above zero")
|
||||||
withUnsafePointer(to: value) { ptr in
|
_ = withUnsafePointer(to: value) { ptr in
|
||||||
_storage.withUnsafeRawPointer {
|
_storage.withUnsafeRawPointer {
|
||||||
memcpy(
|
memcpy(
|
||||||
$0.advanced(by: index),
|
$0.advanced(by: index),
|
||||||
@@ -387,7 +392,7 @@ public struct ByteBuffer {
|
|||||||
count: Int) -> [T]
|
count: Int) -> [T]
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
|
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
@@ -405,7 +410,7 @@ public struct ByteBuffer {
|
|||||||
type: String.Encoding) -> String?
|
type: String.Encoding) -> String?
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
let buf = UnsafeBufferPointer(
|
let buf = UnsafeBufferPointer(
|
||||||
@@ -427,7 +432,7 @@ public struct ByteBuffer {
|
|||||||
count: Int) -> String?
|
count: Int) -> String?
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return _storage.readWithUnsafeRawPointer(position: index) {
|
return _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
String(cString: $0.bindMemory(to: UInt8.self, capacity: count))
|
String(cString: $0.bindMemory(to: UInt8.self, capacity: count))
|
||||||
@@ -446,7 +451,7 @@ public struct ByteBuffer {
|
|||||||
body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T
|
body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T
|
||||||
{
|
{
|
||||||
assert(
|
assert(
|
||||||
index + count <= _storage.capacity,
|
index + count <= capacity,
|
||||||
"Reading out of bounds is illegal")
|
"Reading out of bounds is illegal")
|
||||||
return try _storage.readWithUnsafeRawPointer(position: index) {
|
return try _storage.readWithUnsafeRawPointer(position: index) {
|
||||||
try body(UnsafeRawBufferPointer(start: $0, count: count))
|
try body(UnsafeRawBufferPointer(start: $0, count: count))
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ extension FlexBufferVector {
|
|||||||
json += "["
|
json += "["
|
||||||
for i in 0..<count {
|
for i in 0..<count {
|
||||||
if let val = self[i]?.jsonString() {
|
if let val = self[i]?.jsonString() {
|
||||||
let comma = i == count - 1 ? "" : ", "
|
let comma = i == count &- 1 ? "" : ", "
|
||||||
json += "\(val)\(comma)"
|
json += "\(val)\(comma)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ extension Map {
|
|||||||
json += "{"
|
json += "{"
|
||||||
for i in 0..<count {
|
for i in 0..<count {
|
||||||
if let key = keys[i]?.cString {
|
if let key = keys[i]?.cString {
|
||||||
let comma = i == count - 1 ? "" : ", "
|
let comma = i == count &- 1 ? "" : ", "
|
||||||
let value = values[i]?.jsonString() ?? StaticJSON.null
|
let value = values[i]?.jsonString() ?? StaticJSON.null
|
||||||
json += "\"\(key)\": \(value)\(comma)"
|
json += "\"\(key)\": \(value)\(comma)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ func toFixedTypedVectorElementType(type: FlexBufferType)
|
|||||||
let fixedType: UInt64 = numericCast(
|
let fixedType: UInt64 = numericCast(
|
||||||
type.rawValue &- FlexBufferType.vectorInt2
|
type.rawValue &- FlexBufferType.vectorInt2
|
||||||
.rawValue)
|
.rawValue)
|
||||||
let len: Int = numericCast((fixedType / 3) + 2)
|
let len: Int = numericCast(fixedType.dividedReportingOverflow(by: 3).partialValue &+ 2)
|
||||||
return (
|
return (
|
||||||
FlexBufferType(rawValue: (fixedType % 3) + FlexBufferType.int.rawValue),
|
FlexBufferType(rawValue: (fixedType.quotientAndRemainder(dividingBy: 3).remainder) &+ FlexBufferType.int.rawValue),
|
||||||
len)
|
len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public struct FlexBuffersWriter {
|
|||||||
{
|
{
|
||||||
let vec = createVector(
|
let vec = createVector(
|
||||||
start: start,
|
start: start,
|
||||||
count: stack.count - start,
|
count: stack.count &- start,
|
||||||
step: 1,
|
step: 1,
|
||||||
typed: typed,
|
typed: typed,
|
||||||
fixed: fixed,
|
fixed: fixed,
|
||||||
@@ -211,7 +211,7 @@ public struct FlexBuffersWriter {
|
|||||||
typed: true,
|
typed: true,
|
||||||
fixed: false)
|
fixed: false)
|
||||||
let vec = createVector(
|
let vec = createVector(
|
||||||
start: start + 1,
|
start: start &+ 1,
|
||||||
count: len,
|
count: len,
|
||||||
step: 2,
|
step: 2,
|
||||||
typed: false,
|
typed: false,
|
||||||
@@ -598,7 +598,7 @@ public struct FlexBuffersWriter {
|
|||||||
|
|
||||||
var sloc: UInt = numericCast(writerIndex)
|
var sloc: UInt = numericCast(writerIndex)
|
||||||
key.withCString {
|
key.withCString {
|
||||||
_bb.writeBytes($0, len: len + 1)
|
_bb.writeBytes($0, len: len &+ 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags > .shareKeys {
|
if flags > .shareKeys {
|
||||||
@@ -705,7 +705,7 @@ public struct FlexBuffersWriter {
|
|||||||
/// If this vector is part of a map, we will pre-fix an offset to the keys
|
/// If this vector is part of a map, we will pre-fix an offset to the keys
|
||||||
/// to this vector.
|
/// to this vector.
|
||||||
bitWidth = max(bitWidth, keys!.elementWidth(size: writerIndex, index: 0))
|
bitWidth = max(bitWidth, keys!.elementWidth(size: writerIndex, index: 0))
|
||||||
prefixElements += 2
|
prefixElements = prefixElements &+ 2
|
||||||
}
|
}
|
||||||
var vectorType: FlexBufferType = .key
|
var vectorType: FlexBufferType = .key
|
||||||
|
|
||||||
|
|||||||
@@ -32,32 +32,18 @@ struct _InternalByteBuffer {
|
|||||||
final class Storage {
|
final class Storage {
|
||||||
/// pointer to the start of the buffer object in memory
|
/// pointer to the start of the buffer object in memory
|
||||||
var memory: UnsafeMutableRawPointer
|
var memory: UnsafeMutableRawPointer
|
||||||
/// Capacity of UInt8 the buffer can hold
|
|
||||||
var capacity: Int
|
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
init(count: Int, alignment: Int) {
|
init(count: Int, alignment: Int) {
|
||||||
memory = UnsafeMutableRawPointer.allocate(
|
memory = UnsafeMutableRawPointer.allocate(
|
||||||
byteCount: count,
|
byteCount: count,
|
||||||
alignment: alignment)
|
alignment: alignment)
|
||||||
capacity = count
|
|
||||||
}
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
init(memory: UnsafeMutableRawPointer, capacity: Int, unowned: Bool) {
|
|
||||||
self.memory = memory
|
|
||||||
self.capacity = capacity
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
memory.deallocate()
|
memory.deallocate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
func copy(from ptr: UnsafeRawPointer, count: Int) {
|
|
||||||
memory.copyMemory(from: ptr, byteCount: count)
|
|
||||||
}
|
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
func initialize(for size: Int) {
|
func initialize(for size: Int) {
|
||||||
memset(memory, 0, size)
|
memset(memory, 0, size)
|
||||||
@@ -66,14 +52,11 @@ struct _InternalByteBuffer {
|
|||||||
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
|
/// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
|
||||||
/// - Parameter size: Size of the current object
|
/// - Parameter size: Size of the current object
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
|
func reallocate(
|
||||||
while capacity <= writerSize &+ size {
|
capacity: Int,
|
||||||
capacity = capacity << 1
|
writerSize: Int,
|
||||||
}
|
alignment: Int
|
||||||
|
) {
|
||||||
/// solution take from Apple-NIO
|
|
||||||
capacity = capacity.convertToPowerofTwo
|
|
||||||
|
|
||||||
let newData = UnsafeMutableRawPointer.allocate(
|
let newData = UnsafeMutableRawPointer.allocate(
|
||||||
byteCount: capacity,
|
byteCount: capacity,
|
||||||
alignment: alignment)
|
alignment: alignment)
|
||||||
@@ -97,7 +80,7 @@ struct _InternalByteBuffer {
|
|||||||
/// Public Pointer to the buffer object in memory. This should NOT be modified for any reason
|
/// Public Pointer to the buffer object in memory. This should NOT be modified for any reason
|
||||||
public var memory: UnsafeMutableRawPointer { _storage.memory }
|
public var memory: UnsafeMutableRawPointer { _storage.memory }
|
||||||
/// Current capacity for the buffer
|
/// Current capacity for the buffer
|
||||||
public var capacity: Int { _storage.capacity }
|
public private(set) var capacity: Int
|
||||||
|
|
||||||
/// Returns the written bytes into the ``ByteBuffer``
|
/// Returns the written bytes into the ``ByteBuffer``
|
||||||
public var underlyingBytes: [UInt8] {
|
public var underlyingBytes: [UInt8] {
|
||||||
@@ -113,6 +96,7 @@ struct _InternalByteBuffer {
|
|||||||
/// - allowReadingUnalignedBuffers: allow reading from unaligned buffer
|
/// - allowReadingUnalignedBuffers: allow reading from unaligned buffer
|
||||||
init(initialSize size: Int) {
|
init(initialSize size: Int) {
|
||||||
initialSize = size.convertToPowerofTwo
|
initialSize = size.convertToPowerofTwo
|
||||||
|
capacity = initialSize
|
||||||
_storage = Storage(count: initialSize, alignment: alignment)
|
_storage = Storage(count: initialSize, alignment: alignment)
|
||||||
_storage.initialize(for: initialSize)
|
_storage.initialize(for: initialSize)
|
||||||
}
|
}
|
||||||
@@ -123,8 +107,9 @@ struct _InternalByteBuffer {
|
|||||||
writerIndex = 0
|
writerIndex = 0
|
||||||
alignment = 1
|
alignment = 1
|
||||||
if keepingCapacity {
|
if keepingCapacity {
|
||||||
_storage.initialize(for: _storage.capacity)
|
_storage.initialize(for: capacity)
|
||||||
} else {
|
} else {
|
||||||
|
capacity = initialSize
|
||||||
_storage = Storage(count: initialSize, alignment: alignment)
|
_storage = Storage(count: initialSize, alignment: alignment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,10 +121,22 @@ struct _InternalByteBuffer {
|
|||||||
|
|
||||||
/// Makes sure that buffer has enouch space for each of the objects that will be written into it
|
/// Makes sure that buffer has enouch space for each of the objects that will be written into it
|
||||||
/// - Parameter size: size of object
|
/// - Parameter size: size of object
|
||||||
@inline(__always)
|
@usableFromInline
|
||||||
mutating func ensureSpace(size: Int) {
|
mutating func ensureSpace(size: Int) {
|
||||||
guard size &+ writerIndex > _storage.capacity else { return }
|
guard size &+ writerIndex > capacity else { return }
|
||||||
_storage.reallocate(size, writerSize: writerIndex, alignment: alignment)
|
|
||||||
|
while capacity <= writerIndex &+ size {
|
||||||
|
capacity = capacity << 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// solution take from Apple-NIO
|
||||||
|
capacity = capacity.convertToPowerofTwo
|
||||||
|
|
||||||
|
_storage.reallocate(
|
||||||
|
capacity: capacity,
|
||||||
|
writerSize: writerIndex,
|
||||||
|
alignment: alignment
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@inline(__always)
|
@inline(__always)
|
||||||
@@ -215,7 +212,7 @@ extension _InternalByteBuffer: CustomDebugStringConvertible {
|
|||||||
|
|
||||||
public var debugDescription: String {
|
public var debugDescription: String {
|
||||||
"""
|
"""
|
||||||
buffer located at: \(_storage.memory), with capacity of \(_storage.capacity)
|
buffer located at: \(_storage.memory), with capacity of \(capacity)
|
||||||
{ writerIndex: \(writerIndex) }
|
{ writerIndex: \(writerIndex) }
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ final class ByteBufferTests: XCTestCase {
|
|||||||
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)
|
XCTAssertEqual(memory.baseAddress!, ptr.baseAddress!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,7 @@ import XCTest
|
|||||||
|
|
||||||
final class FlatbuffersVerifierTests: XCTestCase {
|
final class FlatbuffersVerifierTests: XCTestCase {
|
||||||
|
|
||||||
lazy var validStorage: ByteBuffer.Storage = ByteBuffer.Storage(
|
|
||||||
count: Int(FlatBufferMaxSize) - 1)
|
|
||||||
lazy var errorStorage: ByteBuffer.Storage = ByteBuffer.Storage(
|
|
||||||
count: Int(FlatBufferMaxSize) + 1)
|
|
||||||
|
|
||||||
var buffer: ByteBuffer!
|
var buffer: ByteBuffer!
|
||||||
|
|
||||||
var validFlatbuffersObject: ByteBuffer!
|
var validFlatbuffersObject: ByteBuffer!
|
||||||
var invalidFlatbuffersObject: ByteBuffer!
|
var invalidFlatbuffersObject: ByteBuffer!
|
||||||
var invalidFlatbuffersObject2: ByteBuffer!
|
var invalidFlatbuffersObject2: ByteBuffer!
|
||||||
@@ -52,15 +46,13 @@ final class FlatbuffersVerifierTests: XCTestCase {
|
|||||||
|
|
||||||
func testVeriferInitPassing() {
|
func testVeriferInitPassing() {
|
||||||
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
|
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
|
||||||
var buffer = ByteBuffer(assumingMemoryBound: memory, capacity: 8)
|
var buffer = ByteBuffer(assumingMemoryBound: memory, capacity: Int(FlatBufferMaxSize) - 1)
|
||||||
buffer._storage = validStorage
|
|
||||||
XCTAssertNoThrow(try Verifier(buffer: &buffer))
|
XCTAssertNoThrow(try Verifier(buffer: &buffer))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVeriferInitFailing() {
|
func testVeriferInitFailing() {
|
||||||
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
|
let memory = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: 1)
|
||||||
var buffer = ByteBuffer(assumingMemoryBound: memory, capacity: 8)
|
var buffer = ByteBuffer(assumingMemoryBound: memory, capacity: Int(FlatBufferMaxSize) + 1)
|
||||||
buffer._storage = errorStorage
|
|
||||||
XCTAssertThrowsError(try Verifier(buffer: &buffer))
|
XCTAssertThrowsError(try Verifier(buffer: &buffer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user