Squashed 'third_party/flatbuffers/' changes from d6a8dbd26..338393f85
338393f85 Documentation updates for Optional Scalars (#6014) (#6270)
c27bc2d76 [C++] Add ParseJson(), Parser(Parser&&), update fuzzers (#6284)
bc518a512 Fixed FlexBufferBuilder asserting on duplicate keys
100c59054 Added a few more paths for auto labeler (#6281)
e58c18244 Add --require-explicit-ids to require explicit ids (#6277)
69a8b2a57 idl_gen_json_schema.cpp: Changed generation of array element types (#6253)
25eba6f35 fix typo (#6280)
e1f0f75ba Updated Ms build Action to fix build issue (#6279)
faeb04fbe Add type annotation to unspecified array (#6264)
537212afe [Swift] Adds a format file and reformats the swift project (#6250)
6764f25d9 Adds a fix for enum generation (#6263)
Change-Id: I716bd4d2521fb0a673e50a699cef761e042052b2
git-subtree-dir: third_party/flatbuffers
git-subtree-split: 338393f854eb5ba24761a22cd9316ff5cee4eab0
diff --git a/swift/Package.swift b/swift/Package.swift
index 729ad40..5d4c7cc 100644
--- a/swift/Package.swift
+++ b/swift/Package.swift
@@ -1,22 +1,35 @@
// swift-tools-version:5.2
-// The swift-tools-version declares the minimum version of Swift required to build this package.
+/*
+ * Copyright 2020 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 PackageDescription
let package = Package(
- name: "FlatBuffers",
- platforms: [
- .iOS(.v11),
- .macOS(.v10_14),
- ],
- products: [
- .library(
- name: "FlatBuffers",
- targets: ["FlatBuffers"]),
- ],
- targets: [
- .target(
- name: "FlatBuffers",
- dependencies: []),
- ]
-)
+ name: "FlatBuffers",
+ platforms: [
+ .iOS(.v11),
+ .macOS(.v10_14),
+ ],
+ products: [
+ .library(
+ name: "FlatBuffers",
+ targets: ["FlatBuffers"]),
+ ],
+ targets: [
+ .target(
+ name: "FlatBuffers",
+ dependencies: []),
+ ])
diff --git a/swift/Sources/FlatBuffers/ByteBuffer.swift b/swift/Sources/FlatBuffers/ByteBuffer.swift
index 46ae1c5..7df41a7 100644
--- a/swift/Sources/FlatBuffers/ByteBuffer.swift
+++ b/swift/Sources/FlatBuffers/ByteBuffer.swift
@@ -1,345 +1,398 @@
+/*
+ * Copyright 2020 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 Foundation
public struct ByteBuffer {
-
- /// Storage is a container that would hold the memory pointer to solve the issue of
- /// deallocating the memory that was held by (memory: UnsafeMutableRawPointer)
- @usableFromInline final class Storage {
- // This storage doesn't own the memory, therefore, we won't deallocate on deinit.
- private let unowned: Bool
- /// pointer to the start of the buffer object in memory
- var memory: UnsafeMutableRawPointer
- /// Capacity of UInt8 the buffer can hold
- var capacity: Int
-
- init(count: Int, alignment: Int) {
- memory = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: alignment)
- capacity = count
- unowned = false
- }
- init(memory: UnsafeMutableRawPointer, capacity: Int, unowned: Bool) {
- self.memory = memory
- self.capacity = capacity
- self.unowned = unowned
- }
-
- deinit {
- if !unowned {
- memory.deallocate()
- }
- }
-
- func copy(from ptr: UnsafeRawPointer, count: Int) {
- assert(!unowned, "copy should NOT be called on a buffer that is built by assumingMemoryBound")
- memory.copyMemory(from: ptr, byteCount: count)
- }
-
- func initialize(for size: Int) {
- assert(!unowned, "initalize should NOT be called on a buffer that is built by assumingMemoryBound")
- memset(memory, 0, size)
- }
-
- /// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
- /// - Parameter size: Size of the current object
- @usableFromInline internal func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
- let currentWritingIndex = capacity &- writerSize
- while capacity <= writerSize &+ size {
- capacity = capacity << 1
- }
-
- /// solution take from Apple-NIO
- capacity = capacity.convertToPowerofTwo
-
- let newData = UnsafeMutableRawPointer.allocate(byteCount: capacity, alignment: alignment)
- memset(newData, 0, capacity &- writerSize)
- memcpy(newData.advanced(by: capacity &- writerSize), memory.advanced(by: currentWritingIndex), writerSize)
- memory.deallocate()
- memory = newData
- }
- }
-
- @usableFromInline var _storage: Storage
-
- /// The size of the elements written to the buffer + their paddings
- private var _writerSize: Int = 0
- /// Aliginment of the current memory being written to the buffer
- internal 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
- internal var writerIndex: Int { return _storage.capacity &- _writerSize }
+ /// Storage is a container that would hold the memory pointer to solve the issue of
+ /// deallocating the memory that was held by (memory: UnsafeMutableRawPointer)
+ @usableFromInline
+ final class Storage {
+ // This storage doesn't own the memory, therefore, we won't deallocate on deinit.
+ private let unowned: Bool
+ /// pointer to the start of the buffer object in memory
+ var memory: UnsafeMutableRawPointer
+ /// Capacity of UInt8 the buffer can hold
+ var capacity: Int
- /// Reader is the position of the current Writer Index (capacity - size)
- public var reader: Int { return writerIndex }
- /// Current size of the buffer
- public var size: UOffset { return UOffset(_writerSize) }
- /// Public Pointer to the buffer object in memory. This should NOT be modified for any reason
- public var memory: UnsafeMutableRawPointer { return _storage.memory }
- /// Current capacity for the buffer
- public var capacity: Int { return _storage.capacity }
-
- /// Constructor that creates a Flatbuffer object from a UInt8
- /// - Parameter bytes: Array of UInt8
- public init(bytes: [UInt8]) {
- var b = bytes
- _storage = Storage(count: bytes.count, alignment: alignment)
- _writerSize = _storage.capacity
- b.withUnsafeMutableBytes { bufferPointer in
- self._storage.copy(from: bufferPointer.baseAddress!, count: bytes.count)
- }
+ init(count: Int, alignment: Int) {
+ memory = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: alignment)
+ capacity = count
+ unowned = false
}
- /// Constructor that creates a Flatbuffer from the Swift Data type object
- /// - Parameter data: Swift data Object
- public init(data: Data) {
- var b = data
- _storage = Storage(count: data.count, alignment: alignment)
- _writerSize = _storage.capacity
- b.withUnsafeMutableBytes { bufferPointer in
- self._storage.copy(from: bufferPointer.baseAddress!, count: data.count)
- }
+ init(memory: UnsafeMutableRawPointer, capacity: Int, unowned: Bool) {
+ self.memory = memory
+ self.capacity = capacity
+ self.unowned = unowned
}
- /// Constructor that creates a Flatbuffer instance with a size
- /// - Parameter size: Length of the buffer
- init(initialSize size: Int) {
- let size = size.convertToPowerofTwo
- _storage = Storage(count: size, alignment: alignment)
- _storage.initialize(for: size)
- }
-
- #if swift(>=5.0)
- /// Constructor that creates a Flatbuffer object from a ContiguousBytes
- /// - Parameters:
- /// - contiguousBytes: Binary stripe to use as the buffer
- /// - count: amount of readable bytes
- public init<Bytes: ContiguousBytes>(
- contiguousBytes: Bytes,
- count: Int
- ) {
- _storage = Storage(count: count, alignment: alignment)
- _writerSize = _storage.capacity
- contiguousBytes.withUnsafeBytes { buf in
- _storage.copy(from: buf.baseAddress!, count: buf.count)
- }
- }
- #endif
-
- /// Constructor that creates a Flatbuffer from unsafe memory region without copying
- /// - Parameter assumingMemoryBound: The unsafe memory region
- /// - Parameter capacity: The size of the given memory region
- public init(assumingMemoryBound memory: UnsafeMutableRawPointer, capacity: Int) {
- _storage = Storage(memory: memory, capacity: capacity, unowned: true)
- _writerSize = capacity
+ deinit {
+ if !unowned {
+ memory.deallocate()
+ }
}
- /// Creates a copy of the buffer that's being built by calling sizedBuffer
- /// - Parameters:
- /// - memory: Current memory of the buffer
- /// - count: count of bytes
- internal init(memory: UnsafeMutableRawPointer, count: Int) {
- _storage = Storage(count: count, alignment: alignment)
- _storage.copy(from: memory, count: count)
- _writerSize = _storage.capacity
+ func copy(from ptr: UnsafeRawPointer, count: Int) {
+ assert(
+ !unowned,
+ "copy should NOT be called on a buffer that is built by assumingMemoryBound")
+ memory.copyMemory(from: ptr, byteCount: count)
}
- /// Creates a copy of the existing flatbuffer, by copying it to a different memory.
- /// - Parameters:
- /// - memory: Current memory of the buffer
- /// - count: count of bytes
- /// - removeBytes: Removes a number of bytes from the current size
- internal init(memory: UnsafeMutableRawPointer, count: Int, removing removeBytes: Int) {
- _storage = Storage(count: count, alignment: alignment)
- _storage.copy(from: memory, count: count)
- _writerSize = removeBytes
+ func initialize(for size: Int) {
+ assert(
+ !unowned,
+ "initalize should NOT be called on a buffer that is built by assumingMemoryBound")
+ memset(memory, 0, size)
}
- /// Fills the buffer with padding by adding to the writersize
- /// - Parameter padding: Amount of padding between two to be serialized objects
- @usableFromInline mutating func fill(padding: Int) {
- assert(padding >= 0, "Fill should be larger than or equal to zero")
- ensureSpace(size: padding)
- _writerSize = _writerSize &+ (MemoryLayout<UInt8>.size &* padding)
- }
-
- ///Adds an array of type Scalar to the buffer memory
- /// - Parameter elements: An array of Scalars
- @usableFromInline mutating func push<T: Scalar>(elements: [T]) {
- let size = elements.count &* MemoryLayout<T>.size
- ensureSpace(size: size)
- elements.reversed().forEach { (s) in
- push(value: s, len: MemoryLayout.size(ofValue: s))
- }
- }
+ /// Reallocates the buffer incase the object to be written doesnt fit in the current buffer
+ /// - Parameter size: Size of the current object
+ @usableFromInline
+ internal func reallocate(_ size: Int, writerSize: Int, alignment: Int) {
+ let currentWritingIndex = capacity &- writerSize
+ while capacity <= writerSize &+ size {
+ capacity = capacity << 1
+ }
- /// A custom type of structs that are padded according to the flatbuffer padding,
- /// - Parameters:
- /// - value: Pointer to the object in memory
- /// - size: Size of Value being written to the buffer
- @available(*, deprecated, message: "0.9.0 will be removing the following method. Regenerate the code")
- @usableFromInline mutating func push(struct value: UnsafeMutableRawPointer, size: Int) {
- ensureSpace(size: size)
- memcpy(_storage.memory.advanced(by: writerIndex &- size), value, size)
- defer { value.deallocate() }
- _writerSize = _writerSize &+ size
- }
-
- /// Prepares the buffer to receive a struct of certian size.
- /// The alignment of the memory is already handled since we already called preAlign
- /// - Parameter size: size of the struct
- @usableFromInline mutating func prepareBufferToReceiveStruct(of size: Int) {
- ensureSpace(size: size)
- _writerSize = _writerSize &+ size
- }
-
- /// Reverse the input direction to the buffer, since `FlatBuffers` uses a back to front, following method will take current `writerIndex`
- /// and writes front to back into the buffer, respecting the padding & the alignment
- /// - Parameters:
- /// - value: value of type Scalar
- /// - position: position relative to the `writerIndex`
- /// - len: length of the value in terms of bytes
- @usableFromInline mutating func reversePush<T: Scalar>(value: T, position: Int, len: Int) {
- var v = value
- memcpy(_storage.memory.advanced(by: writerIndex &+ position), &v, len)
- }
+ /// solution take from Apple-NIO
+ capacity = capacity.convertToPowerofTwo
- /// Adds an object of type Scalar into the buffer
- /// - Parameters:
- /// - value: Object that will be written to the buffer
- /// - len: Offset to subtract from the WriterIndex
- @usableFromInline mutating func push<T: Scalar>(value: T, len: Int) {
- ensureSpace(size: len)
- var v = value
- memcpy(_storage.memory.advanced(by: writerIndex &- len), &v, len)
- _writerSize = _writerSize &+ len
+ let newData = UnsafeMutableRawPointer.allocate(byteCount: capacity, alignment: alignment)
+ memset(newData, 0, capacity &- writerSize)
+ memcpy(
+ newData.advanced(by: capacity &- writerSize),
+ memory.advanced(by: currentWritingIndex),
+ writerSize)
+ memory.deallocate()
+ memory = newData
}
+ }
- /// Adds a string to the buffer using swift.utf8 object
- /// - Parameter str: String that will be added to the buffer
- /// - Parameter len: length of the string
- @usableFromInline mutating func push(string str: String, len: Int) {
- ensureSpace(size: len)
- if str.utf8.withContiguousStorageIfAvailable({ self.push(bytes: $0, len: len) }) != nil {
- } else {
- let utf8View = str.utf8
- for c in utf8View.reversed() {
- push(value: c, len: 1)
- }
- }
- }
+ @usableFromInline var _storage: Storage
- /// Writes a string to Bytebuffer using UTF8View
- /// - Parameters:
- /// - bytes: Pointer to the view
- /// - len: Size of string
- @usableFromInline mutating internal func push(bytes: UnsafeBufferPointer<String.UTF8View.Element>, len: Int) -> Bool {
- memcpy(_storage.memory.advanced(by: writerIndex &- len), UnsafeRawPointer(bytes.baseAddress!), len)
- _writerSize = _writerSize &+ len
- return true
- }
+ /// The size of the elements written to the buffer + their paddings
+ private var _writerSize: Int = 0
+ /// Aliginment of the current memory being written to the buffer
+ internal 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
+ internal var writerIndex: Int { _storage.capacity &- _writerSize }
- /// Write stores an object into the buffer directly or indirectly.
- ///
- /// Direct: ignores the capacity of buffer which would mean we are referring to the direct point in memory
- /// indirect: takes into respect the current capacity of the buffer (capacity - index), writing to the buffer from the end
- /// - Parameters:
- /// - value: Value that needs to be written to the buffer
- /// - index: index to write to
- /// - direct: Should take into consideration the capacity of the buffer
- func write<T>(value: T, index: Int, direct: Bool = false) {
- var index = index
- if !direct {
- index = _storage.capacity &- index
- }
- assert(index < _storage.capacity, "Write index is out of writing bound")
- assert(index >= 0, "Writer index should be above zero")
- _storage.memory.storeBytes(of: value, toByteOffset: index, as: T.self)
- }
+ /// Reader is the position of the current Writer Index (capacity - size)
+ public var reader: Int { writerIndex }
+ /// Current size of the buffer
+ public var size: UOffset { UOffset(_writerSize) }
+ /// Public Pointer to the buffer object in memory. This should NOT be modified for any reason
+ public var memory: UnsafeMutableRawPointer { _storage.memory }
+ /// Current capacity for the buffer
+ public var capacity: Int { _storage.capacity }
- /// Makes sure that buffer has enouch space for each of the objects that will be written into it
- /// - Parameter size: size of object
- @discardableResult
- @usableFromInline mutating func ensureSpace(size: Int) -> Int {
- if size &+ _writerSize > _storage.capacity {
- _storage.reallocate(size, writerSize: _writerSize, alignment: alignment)
- }
- assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
- return size
+ /// Constructor that creates a Flatbuffer object from a UInt8
+ /// - Parameter bytes: Array of UInt8
+ public init(bytes: [UInt8]) {
+ var b = bytes
+ _storage = Storage(count: bytes.count, alignment: alignment)
+ _writerSize = _storage.capacity
+ b.withUnsafeMutableBytes { bufferPointer in
+ self._storage.copy(from: bufferPointer.baseAddress!, count: bytes.count)
}
-
- /// pops the written VTable if it's already written into the buffer
- /// - Parameter size: size of the `VTable`
- @usableFromInline mutating internal func pop(_ size: Int) {
- assert((_writerSize &- size) > 0, "New size should NOT be a negative number")
- memset(_storage.memory.advanced(by: writerIndex), 0, _writerSize &- size)
- _writerSize = size
- }
-
- /// Clears the current size of the buffer
- mutating public func clearSize() {
- _writerSize = 0
- }
+ }
- /// Clears the current instance of the buffer, replacing it with new memory
- mutating public func clear() {
- _writerSize = 0
- alignment = 1
- _storage.initialize(for: _storage.capacity)
+ /// Constructor that creates a Flatbuffer from the Swift Data type object
+ /// - Parameter data: Swift data Object
+ public init(data: Data) {
+ var b = data
+ _storage = Storage(count: data.count, alignment: alignment)
+ _writerSize = _storage.capacity
+ b.withUnsafeMutableBytes { bufferPointer in
+ self._storage.copy(from: bufferPointer.baseAddress!, count: data.count)
}
-
- /// Reads an object from the buffer
- /// - Parameters:
- /// - def: Type of the object
- /// - position: the index of the object in the buffer
- public func read<T>(def: T.Type, position: Int) -> T {
- assert(position + MemoryLayout<T>.size <= _storage.capacity, "Reading out of bounds is illegal")
- return _storage.memory.advanced(by: position).load(as: T.self)
- }
+ }
- /// Reads a slice from the memory assuming a type of T
- /// - Parameters:
- /// - index: index of the object to be read from the buffer
- /// - count: count of bytes in memory
- public func readSlice<T>(index: Int32,
- count: Int32) -> [T] {
- let _index = Int(index)
- let _count = Int(count)
- assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
- let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: T.self)
- let array = UnsafeBufferPointer(start: start, count: _count)
- return Array(array)
- }
+ /// Constructor that creates a Flatbuffer instance with a size
+ /// - Parameter size: Length of the buffer
+ init(initialSize size: Int) {
+ let size = size.convertToPowerofTwo
+ _storage = Storage(count: size, alignment: alignment)
+ _storage.initialize(for: size)
+ }
- /// Reads a string from the buffer and encodes it to a swift string
- /// - Parameters:
- /// - index: index of the string in the buffer
- /// - count: length of the string
- /// - type: Encoding of the string
- public func readString(at index: Int32,
- count: Int32,
- type: String.Encoding = .utf8) -> String? {
- let _index = Int(index)
- let _count = Int(count)
- assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
- let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: UInt8.self)
- let bufprt = UnsafeBufferPointer(start: start, count: _count)
- return String(bytes: Array(bufprt), encoding: type)
+ #if swift(>=5.0)
+ /// Constructor that creates a Flatbuffer object from a ContiguousBytes
+ /// - Parameters:
+ /// - contiguousBytes: Binary stripe to use as the buffer
+ /// - count: amount of readable bytes
+ public init<Bytes: ContiguousBytes>(
+ contiguousBytes: Bytes,
+ count: Int)
+ {
+ _storage = Storage(count: count, alignment: alignment)
+ _writerSize = _storage.capacity
+ contiguousBytes.withUnsafeBytes { buf in
+ _storage.copy(from: buf.baseAddress!, count: buf.count)
}
+ }
+ #endif
- /// Creates a new Flatbuffer object that's duplicated from the current one
- /// - Parameter removeBytes: the amount of bytes to remove from the current Size
- public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
- assert(removeBytes > 0, "Can NOT remove negative bytes")
- assert(removeBytes < _storage.capacity, "Can NOT remove more bytes than the ones allocated")
- return ByteBuffer(memory: _storage.memory, count: _storage.capacity, removing: _writerSize &- removeBytes)
+ /// Constructor that creates a Flatbuffer from unsafe memory region without copying
+ /// - Parameter assumingMemoryBound: The unsafe memory region
+ /// - Parameter capacity: The size of the given memory region
+ public init(assumingMemoryBound memory: UnsafeMutableRawPointer, capacity: Int) {
+ _storage = Storage(memory: memory, capacity: capacity, unowned: true)
+ _writerSize = capacity
+ }
+
+ /// Creates a copy of the buffer that's being built by calling sizedBuffer
+ /// - Parameters:
+ /// - memory: Current memory of the buffer
+ /// - count: count of bytes
+ internal init(memory: UnsafeMutableRawPointer, count: Int) {
+ _storage = Storage(count: count, alignment: alignment)
+ _storage.copy(from: memory, count: count)
+ _writerSize = _storage.capacity
+ }
+
+ /// Creates a copy of the existing flatbuffer, by copying it to a different memory.
+ /// - Parameters:
+ /// - memory: Current memory of the buffer
+ /// - count: count of bytes
+ /// - removeBytes: Removes a number of bytes from the current size
+ internal init(memory: UnsafeMutableRawPointer, count: Int, removing removeBytes: Int) {
+ _storage = Storage(count: count, alignment: alignment)
+ _storage.copy(from: memory, count: count)
+ _writerSize = removeBytes
+ }
+
+ /// Fills the buffer with padding by adding to the writersize
+ /// - Parameter padding: Amount of padding between two to be serialized objects
+ @usableFromInline
+ mutating func fill(padding: Int) {
+ assert(padding >= 0, "Fill should be larger than or equal to zero")
+ ensureSpace(size: padding)
+ _writerSize = _writerSize &+ (MemoryLayout<UInt8>.size &* padding)
+ }
+
+ ///Adds an array of type Scalar to the buffer memory
+ /// - Parameter elements: An array of Scalars
+ @usableFromInline
+ mutating func push<T: Scalar>(elements: [T]) {
+ let size = elements.count &* MemoryLayout<T>.size
+ ensureSpace(size: size)
+ elements.reversed().forEach { s in
+ push(value: s, len: MemoryLayout.size(ofValue: s))
}
+ }
+
+ /// A custom type of structs that are padded according to the flatbuffer padding,
+ /// - Parameters:
+ /// - value: Pointer to the object in memory
+ /// - size: Size of Value being written to the buffer
+ @available(
+ *,
+ deprecated,
+ message: "0.9.0 will be removing the following method. Regenerate the code")
+ @usableFromInline
+ mutating func push(struct value: UnsafeMutableRawPointer, size: Int) {
+ ensureSpace(size: size)
+ memcpy(_storage.memory.advanced(by: writerIndex &- size), value, size)
+ defer { value.deallocate() }
+ _writerSize = _writerSize &+ size
+ }
+
+ /// Prepares the buffer to receive a struct of certian size.
+ /// The alignment of the memory is already handled since we already called preAlign
+ /// - Parameter size: size of the struct
+ @usableFromInline
+ mutating func prepareBufferToReceiveStruct(of size: Int) {
+ ensureSpace(size: size)
+ _writerSize = _writerSize &+ size
+ }
+
+ /// Reverse the input direction to the buffer, since `FlatBuffers` uses a back to front, following method will take current `writerIndex`
+ /// and writes front to back into the buffer, respecting the padding & the alignment
+ /// - Parameters:
+ /// - value: value of type Scalar
+ /// - position: position relative to the `writerIndex`
+ /// - len: length of the value in terms of bytes
+ @usableFromInline
+ mutating func reversePush<T: Scalar>(value: T, position: Int, len: Int) {
+ var v = value
+ memcpy(_storage.memory.advanced(by: writerIndex &+ position), &v, len)
+ }
+
+ /// Adds an object of type Scalar into the buffer
+ /// - Parameters:
+ /// - value: Object that will be written to the buffer
+ /// - len: Offset to subtract from the WriterIndex
+ @usableFromInline
+ mutating func push<T: Scalar>(value: T, len: Int) {
+ ensureSpace(size: len)
+ var v = value
+ memcpy(_storage.memory.advanced(by: writerIndex &- len), &v, len)
+ _writerSize = _writerSize &+ len
+ }
+
+ /// Adds a string to the buffer using swift.utf8 object
+ /// - Parameter str: String that will be added to the buffer
+ /// - Parameter len: length of the string
+ @usableFromInline
+ mutating func push(string str: String, len: Int) {
+ ensureSpace(size: len)
+ if str.utf8.withContiguousStorageIfAvailable({ self.push(bytes: $0, len: len) }) != nil {
+ } else {
+ let utf8View = str.utf8
+ for c in utf8View.reversed() {
+ push(value: c, len: 1)
+ }
+ }
+ }
+
+ /// Writes a string to Bytebuffer using UTF8View
+ /// - Parameters:
+ /// - bytes: Pointer to the view
+ /// - len: Size of string
+ @usableFromInline
+ mutating internal func push(
+ bytes: UnsafeBufferPointer<String.UTF8View.Element>,
+ len: Int) -> Bool
+ {
+ memcpy(
+ _storage.memory.advanced(by: writerIndex &- len),
+ UnsafeRawPointer(bytes.baseAddress!),
+ len)
+ _writerSize = _writerSize &+ len
+ return true
+ }
+
+ /// Write stores an object into the buffer directly or indirectly.
+ ///
+ /// Direct: ignores the capacity of buffer which would mean we are referring to the direct point in memory
+ /// indirect: takes into respect the current capacity of the buffer (capacity - index), writing to the buffer from the end
+ /// - Parameters:
+ /// - value: Value that needs to be written to the buffer
+ /// - index: index to write to
+ /// - direct: Should take into consideration the capacity of the buffer
+ func write<T>(value: T, index: Int, direct: Bool = false) {
+ var index = index
+ if !direct {
+ index = _storage.capacity &- index
+ }
+ assert(index < _storage.capacity, "Write index is out of writing bound")
+ assert(index >= 0, "Writer index should be above zero")
+ _storage.memory.storeBytes(of: value, toByteOffset: index, as: T.self)
+ }
+
+ /// Makes sure that buffer has enouch space for each of the objects that will be written into it
+ /// - Parameter size: size of object
+ @discardableResult
+ @usableFromInline
+ mutating func ensureSpace(size: Int) -> Int {
+ if size &+ _writerSize > _storage.capacity {
+ _storage.reallocate(size, writerSize: _writerSize, alignment: alignment)
+ }
+ assert(size < FlatBufferMaxSize, "Buffer can't grow beyond 2 Gigabytes")
+ return size
+ }
+
+ /// pops the written VTable if it's already written into the buffer
+ /// - Parameter size: size of the `VTable`
+ @usableFromInline
+ mutating internal func pop(_ size: Int) {
+ assert((_writerSize &- size) > 0, "New size should NOT be a negative number")
+ memset(_storage.memory.advanced(by: writerIndex), 0, _writerSize &- size)
+ _writerSize = size
+ }
+
+ /// Clears the current size of the buffer
+ mutating public func clearSize() {
+ _writerSize = 0
+ }
+
+ /// Clears the current instance of the buffer, replacing it with new memory
+ mutating public func clear() {
+ _writerSize = 0
+ alignment = 1
+ _storage.initialize(for: _storage.capacity)
+ }
+
+ /// Reads an object from the buffer
+ /// - Parameters:
+ /// - def: Type of the object
+ /// - position: the index of the object in the buffer
+ public func read<T>(def: T.Type, position: Int) -> T {
+ assert(
+ position + MemoryLayout<T>.size <= _storage.capacity,
+ "Reading out of bounds is illegal")
+ return _storage.memory.advanced(by: position).load(as: T.self)
+ }
+
+ /// Reads a slice from the memory assuming a type of T
+ /// - Parameters:
+ /// - index: index of the object to be read from the buffer
+ /// - count: count of bytes in memory
+ public func readSlice<T>(
+ index: Int32,
+ count: Int32) -> [T]
+ {
+ let _index = Int(index)
+ let _count = Int(count)
+ assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
+ let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: T.self)
+ let array = UnsafeBufferPointer(start: start, count: _count)
+ return Array(array)
+ }
+
+ /// Reads a string from the buffer and encodes it to a swift string
+ /// - Parameters:
+ /// - index: index of the string in the buffer
+ /// - count: length of the string
+ /// - type: Encoding of the string
+ public func readString(
+ at index: Int32,
+ count: Int32,
+ type: String.Encoding = .utf8) -> String?
+ {
+ let _index = Int(index)
+ let _count = Int(count)
+ assert(_index + _count <= _storage.capacity, "Reading out of bounds is illegal")
+ let start = _storage.memory.advanced(by: _index).assumingMemoryBound(to: UInt8.self)
+ let bufprt = UnsafeBufferPointer(start: start, count: _count)
+ return String(bytes: Array(bufprt), encoding: type)
+ }
+
+ /// Creates a new Flatbuffer object that's duplicated from the current one
+ /// - Parameter removeBytes: the amount of bytes to remove from the current Size
+ public func duplicate(removing removeBytes: Int = 0) -> ByteBuffer {
+ assert(removeBytes > 0, "Can NOT remove negative bytes")
+ assert(removeBytes < _storage.capacity, "Can NOT remove more bytes than the ones allocated")
+ return ByteBuffer(
+ memory: _storage.memory,
+ count: _storage.capacity,
+ removing: _writerSize &- removeBytes)
+ }
}
extension ByteBuffer: CustomDebugStringConvertible {
- public var debugDescription: String {
- """
- buffer located at: \(_storage.memory), with capacity of \(_storage.capacity)
- { writerSize: \(_writerSize), readerSize: \(reader), writerIndex: \(writerIndex) }
- """
- }
+ public var debugDescription: String {
+ """
+ buffer located at: \(_storage.memory), with capacity of \(_storage.capacity)
+ { writerSize: \(_writerSize), readerSize: \(reader), writerIndex: \(writerIndex) }
+ """
+ }
}
diff --git a/swift/Sources/FlatBuffers/Constants.swift b/swift/Sources/FlatBuffers/Constants.swift
index 2b55250..ac541d9 100644
--- a/swift/Sources/FlatBuffers/Constants.swift
+++ b/swift/Sources/FlatBuffers/Constants.swift
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2020 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.
+ */
+
#if os(Linux)
import CoreFoundation
#else
@@ -20,77 +36,77 @@
///
/// Scalar is used to confirm all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
- associatedtype NumericValue
- var convertedEndian: NumericValue { get }
+ associatedtype NumericValue
+ var convertedEndian: NumericValue { get }
}
extension Scalar where Self: FixedWidthInteger {
- /// Converts the value from BigEndian to LittleEndian
- ///
- /// Converts values to little endian on machines that work with BigEndian, however this is NOT TESTED yet.
- public var convertedEndian: NumericValue {
- return self as! Self.NumericValue
- }
+ /// Converts the value from BigEndian to LittleEndian
+ ///
+ /// Converts values to little endian on machines that work with BigEndian, however this is NOT TESTED yet.
+ public var convertedEndian: NumericValue {
+ self as! Self.NumericValue
+ }
}
extension Double: Scalar {
- public typealias NumericValue = UInt64
-
- public var convertedEndian: UInt64 {
- return self.bitPattern.littleEndian
- }
+ public typealias NumericValue = UInt64
+
+ public var convertedEndian: UInt64 {
+ bitPattern.littleEndian
+ }
}
extension Float32: Scalar {
- public typealias NumericValue = UInt32
-
- public var convertedEndian: UInt32 {
- return self.bitPattern.littleEndian
- }
+ public typealias NumericValue = UInt32
+
+ public var convertedEndian: UInt32 {
+ bitPattern.littleEndian
+ }
}
extension Bool: Scalar {
- public var convertedEndian: UInt8 {
- return self == true ? 1 : 0
- }
-
- public typealias NumericValue = UInt8
+ public var convertedEndian: UInt8 {
+ self == true ? 1 : 0
+ }
+
+ public typealias NumericValue = UInt8
}
extension Int: Scalar {
- public typealias NumericValue = Int
+ public typealias NumericValue = Int
}
extension Int8: Scalar {
- public typealias NumericValue = Int8
+ public typealias NumericValue = Int8
}
extension Int16: Scalar {
- public typealias NumericValue = Int16
+ public typealias NumericValue = Int16
}
extension Int32: Scalar {
- public typealias NumericValue = Int32
+ public typealias NumericValue = Int32
}
extension Int64: Scalar {
- public typealias NumericValue = Int64
+ public typealias NumericValue = Int64
}
extension UInt8: Scalar {
- public typealias NumericValue = UInt8
+ public typealias NumericValue = UInt8
}
extension UInt16: Scalar {
- public typealias NumericValue = UInt16
+ public typealias NumericValue = UInt16
}
extension UInt32: Scalar {
- public typealias NumericValue = UInt32
+ public typealias NumericValue = UInt32
}
extension UInt64: Scalar {
- public typealias NumericValue = UInt64
+ public typealias NumericValue = UInt64
}
public func FlatBuffersVersion_1_12_0() {}
diff --git a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
index cfdb20c..71fcab0 100644
--- a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
+++ b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift
@@ -1,602 +1,645 @@
+/*
+ * Copyright 2020 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 Foundation
public struct FlatBufferBuilder {
-
- /// Storage for the Vtables used in the buffer are stored in here, so they would be written later in EndTable
- @usableFromInline internal var _vtableStorage = VTableStorage()
-
- /// Reference Vtables that were already written to the buffer
- private var _vtables: [UOffset] = []
- /// Flatbuffer data will be written into
- private var _bb: ByteBuffer
- /// A check if the buffer is being written into by a different table
- private var isNested = false
- /// Dictonary that stores a map of all the strings that were written to the buffer
- private var stringOffsetMap: [String: Offset<String>] = [:]
- /// A check to see if finish(::) was ever called to retreive data object
- private var finished = false
- /// A check to see if the buffer should serialize Default values
- private var serializeDefaults: Bool
-
- /// Current alignment for the buffer
- var _minAlignment: Int = 0 {
- didSet {
- _bb.alignment = _minAlignment
- }
+
+ /// Storage for the Vtables used in the buffer are stored in here, so they would be written later in EndTable
+ @usableFromInline internal var _vtableStorage = VTableStorage()
+
+ /// Reference Vtables that were already written to the buffer
+ private var _vtables: [UOffset] = []
+ /// Flatbuffer data will be written into
+ private var _bb: ByteBuffer
+ /// A check if the buffer is being written into by a different table
+ private var isNested = false
+ /// Dictonary that stores a map of all the strings that were written to the buffer
+ private var stringOffsetMap: [String: Offset<String>] = [:]
+ /// A check to see if finish(::) was ever called to retreive data object
+ private var finished = false
+ /// A check to see if the buffer should serialize Default values
+ private var serializeDefaults: Bool
+
+ /// Current alignment for the buffer
+ var _minAlignment: Int = 0 {
+ didSet {
+ _bb.alignment = _minAlignment
}
-
- /// Gives a read access to the buffer's size
- public var size: UOffset { return _bb.size }
- /// Data representation of the buffer
- public var data: Data {
- assert(finished, "Data shouldn't be called before finish()")
- return Data(bytes: _bb.memory.advanced(by: _bb.writerIndex),
- count: _bb.capacity &- _bb.writerIndex)
+ }
+
+ /// Gives a read access to the buffer's size
+ public var size: UOffset { _bb.size }
+ /// Data representation of the buffer
+ public var data: Data {
+ assert(finished, "Data shouldn't be called before finish()")
+ return Data(
+ bytes: _bb.memory.advanced(by: _bb.writerIndex),
+ count: _bb.capacity &- _bb.writerIndex)
+ }
+ /// Get's the fully sized buffer stored in memory
+ public var fullSizedByteArray: [UInt8] {
+ let ptr = UnsafeBufferPointer(
+ start: _bb.memory.assumingMemoryBound(to: UInt8.self),
+ count: _bb.capacity)
+ return Array(ptr)
+ }
+ /// Returns the written size of the buffer
+ public var sizedByteArray: [UInt8] {
+ assert(finished, "Data shouldn't be called before finish()")
+ let cp = _bb.capacity &- _bb.writerIndex
+ let start = _bb.memory.advanced(by: _bb.writerIndex)
+ .bindMemory(to: UInt8.self, capacity: cp)
+
+ let ptr = UnsafeBufferPointer(start: start, count: cp)
+ return Array(ptr)
+ }
+ /// Returns the buffer
+ public var buffer: ByteBuffer { _bb }
+
+ /// Returns A sized Buffer from the readable bytes
+ public var sizedBuffer: ByteBuffer {
+ assert(finished, "Data shouldn't be called before finish()")
+ return ByteBuffer(memory: _bb.memory.advanced(by: _bb.reader), count: Int(_bb.size))
+ }
+
+ // MARK: - Init
+
+ /// initialize the buffer with a size
+ /// - Parameters:
+ /// - initialSize: Initial size for the buffer
+ /// - force: Allows default to be serialized into the buffer
+ public init(initialSize: Int32 = 1024, serializeDefaults force: Bool = false) {
+ assert(initialSize > 0, "Size should be greater than zero!")
+ guard isLitteEndian else {
+ fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
}
- /// Get's the fully sized buffer stored in memory
- public var fullSizedByteArray: [UInt8] {
- let ptr = UnsafeBufferPointer(start: _bb.memory.assumingMemoryBound(to: UInt8.self),
- count: _bb.capacity)
- return Array(ptr)
+ serializeDefaults = force
+ _bb = ByteBuffer(initialSize: Int(initialSize))
+ }
+
+ /// Clears the buffer and the builder from it's data
+ mutating public func clear() {
+ _minAlignment = 0
+ isNested = false
+ stringOffsetMap = [:]
+ _vtables = []
+ _vtableStorage.clear()
+ _bb.clear()
+ }
+
+ // MARK: - Create Tables
+
+ /// Checks if the required fields were serialized into the buffer
+ /// - Parameters:
+ /// - table: offset for the table
+ /// - fields: Array of all the important fields to be serialized
+ mutating public func require(table: Offset<UOffset>, fields: [Int32]) {
+ for field in fields {
+ let start = _bb.capacity &- Int(table.o)
+ let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
+ let isOkay = _bb.read(def: VOffset.self, position: startTable &+ Int(field)) != 0
+ assert(isOkay, "Flatbuffers requires the following field")
}
- /// Returns the written size of the buffer
- public var sizedByteArray: [UInt8] {
- assert(finished, "Data shouldn't be called before finish()")
- let cp = _bb.capacity &- _bb.writerIndex
- let start = _bb.memory.advanced(by: _bb.writerIndex)
- .bindMemory(to: UInt8.self, capacity: cp)
-
- let ptr = UnsafeBufferPointer(start: start, count: cp)
- return Array(ptr)
- }
- /// Returns the buffer
- public var buffer: ByteBuffer { return _bb }
-
- /// Returns A sized Buffer from the readable bytes
- public var sizedBuffer: ByteBuffer {
- assert(finished, "Data shouldn't be called before finish()")
- return ByteBuffer(memory: _bb.memory.advanced(by: _bb.reader), count: Int(_bb.size))
- }
-
- // MARK: - Init
-
- /// initialize the buffer with a size
- /// - Parameters:
- /// - initialSize: Initial size for the buffer
- /// - force: Allows default to be serialized into the buffer
- public init(initialSize: Int32 = 1024, serializeDefaults force: Bool = false) {
- assert(initialSize > 0, "Size should be greater than zero!")
- guard isLitteEndian else {
- fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
- }
- serializeDefaults = force
- _bb = ByteBuffer(initialSize: Int(initialSize))
- }
-
- /// Clears the buffer and the builder from it's data
- mutating public func clear() {
- _minAlignment = 0
- isNested = false
- stringOffsetMap = [:]
- _vtables = []
- _vtableStorage.clear()
- _bb.clear()
+ }
+
+ /// Finished the buffer by adding the file id and then calling finish
+ /// - Parameters:
+ /// - offset: Offset of the table
+ /// - fileId: Takes the fileId
+ /// - prefix: if false it wont add the size of the buffer
+ mutating public func finish<T>(offset: Offset<T>, fileId: String, addPrefix prefix: Bool = false) {
+ let size = MemoryLayout<UOffset>.size
+ preAlign(len: size &+ (prefix ? size : 0) &+ FileIdLength, alignment: _minAlignment)
+ assert(fileId.count == FileIdLength, "Flatbuffers requires file id to be 4")
+ _bb.push(string: fileId, len: 4)
+ finish(offset: offset, addPrefix: prefix)
+ }
+
+ /// Finished the buffer by adding the file id, offset, and prefix to it.
+ /// - Parameters:
+ /// - offset: Offset of the table
+ /// - prefix: if false it wont add the size of the buffer
+ mutating public func finish<T>(offset: Offset<T>, addPrefix prefix: Bool = false) {
+ notNested()
+ let size = MemoryLayout<UOffset>.size
+ preAlign(len: size &+ (prefix ? size : 0), alignment: _minAlignment)
+ push(element: refer(to: offset.o))
+ if prefix { push(element: _bb.size) }
+ _vtableStorage.clear()
+ finished = true
+ }
+
+ /// starttable will let the builder know, that a new object is being serialized.
+ ///
+ /// The function will fatalerror if called while there is another object being serialized
+ /// - Parameter numOfFields: Number of elements to be written to the buffer
+ mutating public func startTable(with numOfFields: Int) -> UOffset {
+ notNested()
+ isNested = true
+ _vtableStorage.start(count: numOfFields)
+ return _bb.size
+ }
+
+ /// Endtable will let the builder know that the object that's written to it is completed
+ ///
+ /// This would be called after all the elements are serialized, it will add the vtable into the buffer.
+ /// it will fatalError in case the object is called without starttable, or the object has exceeded the limit of
+ /// 2GB,
+ /// - Parameter startOffset:Start point of the object written
+ /// - returns: The root of the table
+ mutating public func endTable(at startOffset: UOffset) -> UOffset {
+ assert(isNested, "Calling endtable without calling starttable")
+ let sizeofVoffset = MemoryLayout<VOffset>.size
+ let vTableOffset = push(element: SOffset(0))
+
+ let tableObjectSize = vTableOffset &- startOffset
+ assert(tableObjectSize < 0x10000, "Buffer can't grow beyond 2 Gigabytes")
+ let _max = Int(_vtableStorage.maxOffset) &+ sizeofVoffset
+
+ _bb.fill(padding: _max)
+ _bb.write(
+ value: VOffset(tableObjectSize),
+ index: _bb.writerIndex &+ sizeofVoffset,
+ direct: true)
+ _bb.write(value: VOffset(_max), index: _bb.writerIndex, direct: true)
+
+ var itr = 0
+ while itr < _vtableStorage.writtenIndex {
+ let loaded = _vtableStorage.load(at: itr)
+ itr = itr &+ _vtableStorage.size
+ guard loaded.offset != 0 else { continue }
+ let _index = (_bb.writerIndex &+ Int(loaded.position))
+ _bb.write(value: VOffset(vTableOffset &- loaded.offset), index: _index, direct: true)
}
- // MARK: - Create Tables
-
- /// Checks if the required fields were serialized into the buffer
- /// - Parameters:
- /// - table: offset for the table
- /// - fields: Array of all the important fields to be serialized
- mutating public func require(table: Offset<UOffset>, fields: [Int32]) {
- for field in fields {
- let start = _bb.capacity &- Int(table.o)
- let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
- let isOkay = _bb.read(def: VOffset.self, position: startTable &+ Int(field)) != 0
- assert(isOkay, "Flatbuffers requires the following field")
- }
- }
-
- /// Finished the buffer by adding the file id and then calling finish
- /// - Parameters:
- /// - offset: Offset of the table
- /// - fileId: Takes the fileId
- /// - prefix: if false it wont add the size of the buffer
- mutating public func finish<T>(offset: Offset<T>, fileId: String, addPrefix prefix: Bool = false) {
- let size = MemoryLayout<UOffset>.size
- preAlign(len: size &+ (prefix ? size : 0) &+ FileIdLength, alignment: _minAlignment)
- assert(fileId.count == FileIdLength, "Flatbuffers requires file id to be 4")
- _bb.push(string: fileId, len: 4)
- finish(offset: offset, addPrefix: prefix)
- }
-
- /// Finished the buffer by adding the file id, offset, and prefix to it.
- /// - Parameters:
- /// - offset: Offset of the table
- /// - prefix: if false it wont add the size of the buffer
- mutating public func finish<T>(offset: Offset<T>, addPrefix prefix: Bool = false) {
- notNested()
- let size = MemoryLayout<UOffset>.size
- preAlign(len: size &+ (prefix ? size : 0), alignment: _minAlignment)
- push(element: refer(to: offset.o))
- if prefix { push(element: _bb.size) }
- _vtableStorage.clear()
- finished = true
- }
-
- /// starttable will let the builder know, that a new object is being serialized.
- ///
- /// The function will fatalerror if called while there is another object being serialized
- /// - Parameter numOfFields: Number of elements to be written to the buffer
- mutating public func startTable(with numOfFields: Int) -> UOffset {
- notNested()
- isNested = true
- _vtableStorage.start(count: numOfFields)
- return _bb.size
- }
-
- /// Endtable will let the builder know that the object that's written to it is completed
- ///
- /// This would be called after all the elements are serialized, it will add the vtable into the buffer.
- /// it will fatalError in case the object is called without starttable, or the object has exceeded the limit of
- /// 2GB,
- /// - Parameter startOffset:Start point of the object written
- /// - returns: The root of the table
- mutating public func endTable(at startOffset: UOffset) -> UOffset {
- assert(isNested, "Calling endtable without calling starttable")
- let sizeofVoffset = MemoryLayout<VOffset>.size
- let vTableOffset = push(element: SOffset(0))
-
- let tableObjectSize = vTableOffset &- startOffset
- assert(tableObjectSize < 0x10000, "Buffer can't grow beyond 2 Gigabytes")
- let _max = Int(_vtableStorage.maxOffset) &+ sizeofVoffset
-
- _bb.fill(padding: _max)
- _bb.write(value: VOffset(tableObjectSize), index: _bb.writerIndex &+ sizeofVoffset, direct: true)
- _bb.write(value: VOffset(_max), index: _bb.writerIndex, direct: true)
-
- var itr = 0
- while itr < _vtableStorage.writtenIndex {
- let loaded = _vtableStorage.load(at: itr)
- itr = itr &+ _vtableStorage.size
- guard loaded.offset != 0 else { continue }
- let _index = (_bb.writerIndex &+ Int(loaded.position))
- _bb.write(value: VOffset(vTableOffset &- loaded.offset), index: _index, direct: true)
- }
-
- _vtableStorage.clear()
- let vt_use = _bb.size
-
- var isAlreadyAdded: Int?
-
- let vt2 = _bb.memory.advanced(by: _bb.writerIndex)
- let len2 = vt2.load(fromByteOffset: 0, as: Int16.self)
+ _vtableStorage.clear()
+ let vt_use = _bb.size
- for table in _vtables {
- let position = _bb.capacity &- Int(table)
- let vt1 = _bb.memory.advanced(by: position)
- let len1 = _bb.read(def: Int16.self, position: position)
- if (len2 != len1 || 0 != memcmp(vt1, vt2, Int(len2))) { continue }
-
- isAlreadyAdded = Int(table)
- break
- }
-
- if let offset = isAlreadyAdded {
- let vTableOff = Int(vTableOffset)
- let space = _bb.capacity &- vTableOff
- _bb.write(value: Int32(offset &- vTableOff), index: space, direct: true)
- _bb.pop(_bb.capacity &- space)
- } else {
- _bb.write(value: Int32(vt_use &- vTableOffset), index: Int(vTableOffset))
- _vtables.append(_bb.size)
- }
- isNested = false
- return vTableOffset
- }
-
- // MARK: - Builds Buffer
-
- /// asserts to see if the object is not nested
- @usableFromInline mutating internal func notNested() {
- assert(!isNested, "Object serialization must not be nested")
- }
-
- /// Changes the minimuim alignment of the buffer
- /// - Parameter size: size of the current alignment
- @usableFromInline mutating internal func minAlignment(size: Int) {
- if size > _minAlignment {
- _minAlignment = size
- }
- }
-
- /// Gets the padding for the current element
- /// - Parameters:
- /// - bufSize: Current size of the buffer + the offset of the object to be written
- /// - elementSize: Element size
- @usableFromInline mutating internal func padding(bufSize: UInt32, elementSize: UInt32) -> UInt32 {
- ((~bufSize) &+ 1) & (elementSize - 1)
- }
-
- /// Prealigns the buffer before writting a new object into the buffer
- /// - Parameters:
- /// - len:Length of the object
- /// - alignment: Alignment type
- @usableFromInline mutating internal func preAlign(len: Int, alignment: Int) {
- minAlignment(size: alignment)
- _bb.fill(padding: Int(padding(bufSize: _bb.size &+ UOffset(len), elementSize: UOffset(alignment))))
- }
-
- /// Prealigns the buffer before writting a new object into the buffer
- /// - Parameters:
- /// - len: Length of the object
- /// - type: Type of the object to be written
- @usableFromInline mutating internal func preAlign<T: Scalar>(len: Int, type: T.Type) {
- preAlign(len: len, alignment: MemoryLayout<T>.size)
- }
-
- /// Refers to an object that's written in the buffer
- /// - Parameter off: the objects index value
- @usableFromInline mutating internal func refer(to off: UOffset) -> UOffset {
- let size = MemoryLayout<UOffset>.size
- preAlign(len: size, alignment: size)
- return _bb.size &- off &+ UInt32(size)
- }
-
- /// Tracks the elements written into the buffer
- /// - Parameters:
- /// - offset: The offset of the element witten
- /// - position: The position of the element
- @usableFromInline mutating internal func track(offset: UOffset, at position: VOffset) {
- _vtableStorage.add(loc: FieldLoc(offset: offset, position: position))
+ var isAlreadyAdded: Int?
+
+ let vt2 = _bb.memory.advanced(by: _bb.writerIndex)
+ let len2 = vt2.load(fromByteOffset: 0, as: Int16.self)
+
+ for table in _vtables {
+ let position = _bb.capacity &- Int(table)
+ let vt1 = _bb.memory.advanced(by: position)
+ let len1 = _bb.read(def: Int16.self, position: position)
+ if len2 != len1 || 0 != memcmp(vt1, vt2, Int(len2)) { continue }
+
+ isAlreadyAdded = Int(table)
+ break
}
- // MARK: - Vectors
-
- /// Starts a vector of length and Element size
- mutating public func startVector(_ len: Int, elementSize: Int) {
- notNested()
- isNested = true
- preAlign(len: len &* elementSize, type: UOffset.self)
- preAlign(len: len &* elementSize, alignment: elementSize)
+ if let offset = isAlreadyAdded {
+ let vTableOff = Int(vTableOffset)
+ let space = _bb.capacity &- vTableOff
+ _bb.write(value: Int32(offset &- vTableOff), index: space, direct: true)
+ _bb.pop(_bb.capacity &- space)
+ } else {
+ _bb.write(value: Int32(vt_use &- vTableOffset), index: Int(vTableOffset))
+ _vtables.append(_bb.size)
}
-
- /// Ends the vector of at length
- ///
- /// The current function will fatalError if startVector is called before serializing the vector
- /// - Parameter len: Length of the buffer
- mutating public func endVector(len: Int) -> UOffset {
- assert(isNested, "Calling endVector without calling startVector")
- isNested = false
- return push(element: Int32(len))
- }
-
- /// Creates a vector of type Scalar in the buffer
- /// - Parameter elements: elements to be written into the buffer
- /// - returns: Offset of the vector
- mutating public func createVector<T: Scalar>(_ elements: [T]) -> Offset<UOffset> {
- return createVector(elements, size: elements.count)
- }
-
- /// Creates a vector of type Scalar in the buffer
- /// - Parameter elements: Elements to be written into the buffer
- /// - Parameter size: Count of elements
- /// - returns: Offset of the vector
- mutating public func createVector<T: Scalar>(_ elements: [T], size: Int) -> Offset<UOffset> {
- let size = size
- startVector(size, elementSize: MemoryLayout<T>.size)
- _bb.push(elements: elements)
- return Offset(offset: endVector(len: size))
- }
-
- /// Creates a vector of type Enums in the buffer
- /// - Parameter elements: elements to be written into the buffer
- /// - returns: Offset of the vector
- mutating public func createVector<T: Enum>(_ elements: [T]) -> Offset<UOffset> {
- return createVector(elements, size: elements.count)
- }
-
- /// Creates a vector of type Enums in the buffer
- /// - Parameter elements: Elements to be written into the buffer
- /// - Parameter size: Count of elements
- /// - returns: Offset of the vector
- mutating public func createVector<T: Enum>(_ elements: [T], size: Int) -> Offset<UOffset> {
- let size = size
- startVector(size, elementSize: T.byteSize)
- for e in elements.reversed() {
- _bb.push(value: e.value, len: T.byteSize)
- }
- return Offset(offset: endVector(len: size))
- }
-
- /// Creates a vector of type Offsets in the buffer
- /// - Parameter offsets:Array of offsets of type T
- /// - returns: Offset of the vector
- mutating public func createVector<T>(ofOffsets offsets: [Offset<T>]) -> Offset<UOffset> {
- createVector(ofOffsets: offsets, len: offsets.count)
- }
-
- /// Creates a vector of type Offsets in the buffer
- /// - Parameter elements: Array of offsets of type T
- /// - Parameter size: Count of elements
- /// - returns: Offset of the vector
- mutating public func createVector<T>(ofOffsets offsets: [Offset<T>], len: Int) -> Offset<UOffset> {
- startVector(len, elementSize: MemoryLayout<Offset<T>>.size)
- for o in offsets.reversed() {
- push(element: o)
- }
- return Offset(offset: endVector(len: len))
- }
-
- /// Creates a vector of Strings
- /// - Parameter str: a vector of strings that will be written into the buffer
- /// - returns: Offset of the vector
- mutating public func createVector(ofStrings str: [String]) -> Offset<UOffset> {
- var offsets: [Offset<String>] = []
- for s in str {
- offsets.append(create(string: s))
- }
- return createVector(ofOffsets: offsets)
- }
-
- /// Creates a vector of Flatbuffer structs.
- ///
- /// The function takes a Type to know what size it is, and alignment
- /// - Parameters:
- /// - structs: An array of UnsafeMutableRawPointer
- /// - type: Type of the struct being written
- /// - returns: Offset of the vector
- @available(*, deprecated, message: "0.9.0 will be removing the following method. Regenerate the code")
- mutating public func createVector<T: Readable>(structs: [UnsafeMutableRawPointer],
- type: T.Type) -> Offset<UOffset> {
- startVector(structs.count &* T.size, elementSize: T.alignment)
- for i in structs.reversed() {
- create(struct: i, type: T.self)
- }
- return Offset(offset: endVector(len: structs.count))
- }
-
- /// Starts a vector of struct that considers the size and alignment of the struct
- /// - Parameters:
- /// - count: number of elements to be written
- /// - size: size of struct
- /// - alignment: alignment of the struct
- mutating public func startVectorOfStructs(count: Int, size: Int, alignment: Int) {
- startVector(count &* size, elementSize: alignment)
- }
-
- /// Ends the vector of structs and writtens the current offset
- /// - Parameter count: number of written elements
- /// - Returns: Offset of type UOffset
- mutating public func endVectorOfStructs(count: Int) -> Offset<UOffset> {
- return Offset<UOffset>(offset: endVector(len: count))
- }
+ isNested = false
+ return vTableOffset
+ }
- // MARK: - Inserting Structs
-
- /// Writes a Flatbuffer struct into the buffer
- /// - Parameters:
- /// - s: Flatbuffer struct
- /// - type: Type of the element to be serialized
- /// - returns: Offset of the Object
- @available(*, deprecated, message: "0.9.0 will be removing the following method. Regenerate the code")
- @discardableResult
- mutating public func create<T: Readable>(struct s: UnsafeMutableRawPointer,
- type: T.Type) -> Offset<UOffset> {
- let size = T.size
- preAlign(len: size, alignment: T.alignment)
- _bb.push(struct: s, size: size)
- return Offset(offset: _bb.size)
+ // MARK: - Builds Buffer
+
+ /// asserts to see if the object is not nested
+ @usableFromInline
+ mutating internal func notNested() {
+ assert(!isNested, "Object serialization must not be nested")
+ }
+
+ /// Changes the minimuim alignment of the buffer
+ /// - Parameter size: size of the current alignment
+ @usableFromInline
+ mutating internal func minAlignment(size: Int) {
+ if size > _minAlignment {
+ _minAlignment = size
}
-
- /// prepares the ByteBuffer to receive a struct of size and alignment
- /// - Parameters:
- /// - size: size of written struct
- /// - alignment: alignment of written struct
- mutating public func createStructOf(size: Int, alignment: Int) {
- preAlign(len: size, alignment: alignment)
- _bb.prepareBufferToReceiveStruct(of: size)
+ }
+
+ /// Gets the padding for the current element
+ /// - Parameters:
+ /// - bufSize: Current size of the buffer + the offset of the object to be written
+ /// - elementSize: Element size
+ @usableFromInline
+ mutating internal func padding(bufSize: UInt32, elementSize: UInt32) -> UInt32 {
+ ((~bufSize) &+ 1) & (elementSize - 1)
+ }
+
+ /// Prealigns the buffer before writting a new object into the buffer
+ /// - Parameters:
+ /// - len:Length of the object
+ /// - alignment: Alignment type
+ @usableFromInline
+ mutating internal func preAlign(len: Int, alignment: Int) {
+ minAlignment(size: alignment)
+ _bb.fill(padding: Int(padding(
+ bufSize: _bb.size &+ UOffset(len),
+ elementSize: UOffset(alignment))))
+ }
+
+ /// Prealigns the buffer before writting a new object into the buffer
+ /// - Parameters:
+ /// - len: Length of the object
+ /// - type: Type of the object to be written
+ @usableFromInline
+ mutating internal func preAlign<T: Scalar>(len: Int, type: T.Type) {
+ preAlign(len: len, alignment: MemoryLayout<T>.size)
+ }
+
+ /// Refers to an object that's written in the buffer
+ /// - Parameter off: the objects index value
+ @usableFromInline
+ mutating internal func refer(to off: UOffset) -> UOffset {
+ let size = MemoryLayout<UOffset>.size
+ preAlign(len: size, alignment: size)
+ return _bb.size &- off &+ UInt32(size)
+ }
+
+ /// Tracks the elements written into the buffer
+ /// - Parameters:
+ /// - offset: The offset of the element witten
+ /// - position: The position of the element
+ @usableFromInline
+ mutating internal func track(offset: UOffset, at position: VOffset) {
+ _vtableStorage.add(loc: FieldLoc(offset: offset, position: position))
+ }
+
+ // MARK: - Vectors
+
+ /// Starts a vector of length and Element size
+ mutating public func startVector(_ len: Int, elementSize: Int) {
+ notNested()
+ isNested = true
+ preAlign(len: len &* elementSize, type: UOffset.self)
+ preAlign(len: len &* elementSize, alignment: elementSize)
+ }
+
+ /// Ends the vector of at length
+ ///
+ /// The current function will fatalError if startVector is called before serializing the vector
+ /// - Parameter len: Length of the buffer
+ mutating public func endVector(len: Int) -> UOffset {
+ assert(isNested, "Calling endVector without calling startVector")
+ isNested = false
+ return push(element: Int32(len))
+ }
+
+ /// Creates a vector of type Scalar in the buffer
+ /// - Parameter elements: elements to be written into the buffer
+ /// - returns: Offset of the vector
+ mutating public func createVector<T: Scalar>(_ elements: [T]) -> Offset<UOffset> {
+ createVector(elements, size: elements.count)
+ }
+
+ /// Creates a vector of type Scalar in the buffer
+ /// - Parameter elements: Elements to be written into the buffer
+ /// - Parameter size: Count of elements
+ /// - returns: Offset of the vector
+ mutating public func createVector<T: Scalar>(_ elements: [T], size: Int) -> Offset<UOffset> {
+ let size = size
+ startVector(size, elementSize: MemoryLayout<T>.size)
+ _bb.push(elements: elements)
+ return Offset(offset: endVector(len: size))
+ }
+
+ /// Creates a vector of type Enums in the buffer
+ /// - Parameter elements: elements to be written into the buffer
+ /// - returns: Offset of the vector
+ mutating public func createVector<T: Enum>(_ elements: [T]) -> Offset<UOffset> {
+ createVector(elements, size: elements.count)
+ }
+
+ /// Creates a vector of type Enums in the buffer
+ /// - Parameter elements: Elements to be written into the buffer
+ /// - Parameter size: Count of elements
+ /// - returns: Offset of the vector
+ mutating public func createVector<T: Enum>(_ elements: [T], size: Int) -> Offset<UOffset> {
+ let size = size
+ startVector(size, elementSize: T.byteSize)
+ for e in elements.reversed() {
+ _bb.push(value: e.value, len: T.byteSize)
}
-
- /// Adds scalars front to back instead of the default behavior of the normal add
- /// - Parameters:
- /// - v: element of type Scalar
- /// - postion: position relative to the `writerIndex`
- mutating public func reverseAdd<T: Scalar>(v: T, postion: Int) {
- _bb.reversePush(value: v,
- position: postion,
- len: MemoryLayout<T>.size)
+ return Offset(offset: endVector(len: size))
+ }
+
+ /// Creates a vector of type Offsets in the buffer
+ /// - Parameter offsets:Array of offsets of type T
+ /// - returns: Offset of the vector
+ mutating public func createVector<T>(ofOffsets offsets: [Offset<T>]) -> Offset<UOffset> {
+ createVector(ofOffsets: offsets, len: offsets.count)
+ }
+
+ /// Creates a vector of type Offsets in the buffer
+ /// - Parameter elements: Array of offsets of type T
+ /// - Parameter size: Count of elements
+ /// - returns: Offset of the vector
+ mutating public func createVector<T>(ofOffsets offsets: [Offset<T>], len: Int) -> Offset<UOffset> {
+ startVector(len, elementSize: MemoryLayout<Offset<T>>.size)
+ for o in offsets.reversed() {
+ push(element: o)
}
-
- /// Ends the struct and returns the current buffer size
- /// - Returns: Offset of type UOffset
- @discardableResult
- public func endStruct() -> Offset<UOffset> {
- return Offset(offset: _bb.size)
+ return Offset(offset: endVector(len: len))
+ }
+
+ /// Creates a vector of Strings
+ /// - Parameter str: a vector of strings that will be written into the buffer
+ /// - returns: Offset of the vector
+ mutating public func createVector(ofStrings str: [String]) -> Offset<UOffset> {
+ var offsets: [Offset<String>] = []
+ for s in str {
+ offsets.append(create(string: s))
}
-
- /// Adds the offset of a struct into the vTable
- ///
- /// The function fatalErrors if we pass an offset that is out of range
- /// - Parameter o: offset
- mutating public func add(structOffset o: VOffset) {
- _vtableStorage.add(loc: FieldLoc(offset: _bb.size, position: VOffset(o)))
+ return createVector(ofOffsets: offsets)
+ }
+
+ /// Creates a vector of Flatbuffer structs.
+ ///
+ /// The function takes a Type to know what size it is, and alignment
+ /// - Parameters:
+ /// - structs: An array of UnsafeMutableRawPointer
+ /// - type: Type of the struct being written
+ /// - returns: Offset of the vector
+ @available(
+ *,
+ deprecated,
+ message: "0.9.0 will be removing the following method. Regenerate the code")
+ mutating public func createVector<T: Readable>(
+ structs: [UnsafeMutableRawPointer],
+ type: T.Type) -> Offset<UOffset>
+ {
+ startVector(structs.count &* T.size, elementSize: T.alignment)
+ for i in structs.reversed() {
+ create(struct: i, type: T.self)
}
-
- // MARK: - Inserting Strings
-
- /// Insets a string into the buffer using UTF8
- /// - Parameter str: String to be serialized
- /// - returns: The strings offset in the buffer
- mutating public func create(string str: String?) -> Offset<String> {
- guard let str = str else { return Offset() }
- let len = str.utf8.count
- notNested()
- preAlign(len: len &+ 1, type: UOffset.self)
- _bb.fill(padding: 1)
- _bb.push(string: str, len: len)
- push(element: UOffset(len))
- return Offset(offset: _bb.size)
+ return Offset(offset: endVector(len: structs.count))
+ }
+
+ /// Starts a vector of struct that considers the size and alignment of the struct
+ /// - Parameters:
+ /// - count: number of elements to be written
+ /// - size: size of struct
+ /// - alignment: alignment of the struct
+ mutating public func startVectorOfStructs(count: Int, size: Int, alignment: Int) {
+ startVector(count &* size, elementSize: alignment)
+ }
+
+ /// Ends the vector of structs and writtens the current offset
+ /// - Parameter count: number of written elements
+ /// - Returns: Offset of type UOffset
+ mutating public func endVectorOfStructs(count: Int) -> Offset<UOffset> {
+ Offset<UOffset>(offset: endVector(len: count))
+ }
+
+ // MARK: - Inserting Structs
+
+ /// Writes a Flatbuffer struct into the buffer
+ /// - Parameters:
+ /// - s: Flatbuffer struct
+ /// - type: Type of the element to be serialized
+ /// - returns: Offset of the Object
+ @available(
+ *,
+ deprecated,
+ message: "0.9.0 will be removing the following method. Regenerate the code")
+ @discardableResult
+ mutating public func create<T: Readable>(
+ struct s: UnsafeMutableRawPointer,
+ type: T.Type) -> Offset<UOffset>
+ {
+ let size = T.size
+ preAlign(len: size, alignment: T.alignment)
+ _bb.push(struct: s, size: size)
+ return Offset(offset: _bb.size)
+ }
+
+ /// prepares the ByteBuffer to receive a struct of size and alignment
+ /// - Parameters:
+ /// - size: size of written struct
+ /// - alignment: alignment of written struct
+ mutating public func createStructOf(size: Int, alignment: Int) {
+ preAlign(len: size, alignment: alignment)
+ _bb.prepareBufferToReceiveStruct(of: size)
+ }
+
+ /// Adds scalars front to back instead of the default behavior of the normal add
+ /// - Parameters:
+ /// - v: element of type Scalar
+ /// - postion: position relative to the `writerIndex`
+ mutating public func reverseAdd<T: Scalar>(v: T, postion: Int) {
+ _bb.reversePush(
+ value: v,
+ position: postion,
+ len: MemoryLayout<T>.size)
+ }
+
+ /// Ends the struct and returns the current buffer size
+ /// - Returns: Offset of type UOffset
+ @discardableResult
+ public func endStruct() -> Offset<UOffset> {
+ Offset(offset: _bb.size)
+ }
+
+ /// Adds the offset of a struct into the vTable
+ ///
+ /// The function fatalErrors if we pass an offset that is out of range
+ /// - Parameter o: offset
+ mutating public func add(structOffset o: VOffset) {
+ _vtableStorage.add(loc: FieldLoc(offset: _bb.size, position: VOffset(o)))
+ }
+
+ // MARK: - Inserting Strings
+
+ /// Insets a string into the buffer using UTF8
+ /// - Parameter str: String to be serialized
+ /// - returns: The strings offset in the buffer
+ mutating public func create(string str: String?) -> Offset<String> {
+ guard let str = str else { return Offset() }
+ let len = str.utf8.count
+ notNested()
+ preAlign(len: len &+ 1, type: UOffset.self)
+ _bb.fill(padding: 1)
+ _bb.push(string: str, len: len)
+ push(element: UOffset(len))
+ return Offset(offset: _bb.size)
+ }
+
+ /// Inserts a shared string to the buffer
+ ///
+ /// The function checks the stringOffsetmap if it's seen a similar string before
+ /// - Parameter str: String to be serialized
+ /// - returns: The strings offset in the buffer
+ mutating public func createShared(string str: String?) -> Offset<String> {
+ guard let str = str else { return Offset() }
+ if let offset = stringOffsetMap[str] {
+ return offset
}
-
- /// Inserts a shared string to the buffer
- ///
- /// The function checks the stringOffsetmap if it's seen a similar string before
- /// - Parameter str: String to be serialized
- /// - returns: The strings offset in the buffer
- mutating public func createShared(string str: String?) -> Offset<String> {
- guard let str = str else { return Offset() }
- if let offset = stringOffsetMap[str] {
- return offset
- }
- let offset = create(string: str)
- stringOffsetMap[str] = offset
- return offset
- }
-
- // MARK: - Inseting offsets
-
- /// Adds the offset of an object into the buffer
- /// - Parameters:
- /// - offset: Offset of another object to be written
- /// - position: The predefined position of the object
- mutating public func add<T>(offset: Offset<T>, at position: VOffset) {
- if offset.isEmpty { return }
- add(element: refer(to: offset.o), def: 0, at: position)
- }
-
- /// Pushes a value of type offset into the buffer
- /// - Parameter o: Offset
- /// - returns: Position of the offset
- @discardableResult
- mutating public func push<T>(element o: Offset<T>) -> UOffset {
- push(element: refer(to: o.o))
- }
-
- // MARK: - Inserting Scalars to Buffer
-
- /// Adds a value into the buffer of type Scalar
- ///
- /// - Parameters:
- /// - element: Element to insert
- /// - def: Default value for that element
- /// - position: The predefined position of the element
- mutating public func add<T: Scalar>(element: T, def: T, at position: VOffset) {
- if (element == def && !serializeDefaults) { return }
- track(offset: push(element: element), at: position)
- }
-
- /// Adds a value into the buffer of type optional Scalar
- /// - Parameters:
- /// - element: Optional element of type scalar
- /// - position: The predefined position of the element
- mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
- guard let element = element else { return }
- track(offset: push(element: element), at: position)
- }
-
- /// Pushes the values into the buffer
- /// - Parameter element: Element to insert
- /// - returns: Postion of the Element
- @discardableResult
- mutating public func push<T: Scalar>(element: T) -> UOffset {
- let size = MemoryLayout<T>.size
- preAlign(len: size,
- alignment: size)
- _bb.push(value: element, len: size)
- return _bb.size
- }
-
+ let offset = create(string: str)
+ stringOffsetMap[str] = offset
+ return offset
+ }
+
+ // MARK: - Inseting offsets
+
+ /// Adds the offset of an object into the buffer
+ /// - Parameters:
+ /// - offset: Offset of another object to be written
+ /// - position: The predefined position of the object
+ mutating public func add<T>(offset: Offset<T>, at position: VOffset) {
+ if offset.isEmpty { return }
+ add(element: refer(to: offset.o), def: 0, at: position)
+ }
+
+ /// Pushes a value of type offset into the buffer
+ /// - Parameter o: Offset
+ /// - returns: Position of the offset
+ @discardableResult
+ mutating public func push<T>(element o: Offset<T>) -> UOffset {
+ push(element: refer(to: o.o))
+ }
+
+ // MARK: - Inserting Scalars to Buffer
+
+ /// Adds a value into the buffer of type Scalar
+ ///
+ /// - Parameters:
+ /// - element: Element to insert
+ /// - def: Default value for that element
+ /// - position: The predefined position of the element
+ mutating public func add<T: Scalar>(element: T, def: T, at position: VOffset) {
+ if element == def && !serializeDefaults { return }
+ track(offset: push(element: element), at: position)
+ }
+
+ /// Adds a value into the buffer of type optional Scalar
+ /// - Parameters:
+ /// - element: Optional element of type scalar
+ /// - position: The predefined position of the element
+ mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
+ guard let element = element else { return }
+ track(offset: push(element: element), at: position)
+ }
+
+ /// Pushes the values into the buffer
+ /// - Parameter element: Element to insert
+ /// - returns: Postion of the Element
+ @discardableResult
+ mutating public func push<T: Scalar>(element: T) -> UOffset {
+ let size = MemoryLayout<T>.size
+ preAlign(
+ len: size,
+ alignment: size)
+ _bb.push(value: element, len: size)
+ return _bb.size
+ }
+
}
extension FlatBufferBuilder: CustomDebugStringConvertible {
-
- public var debugDescription: String {
- """
- buffer debug:
- \(_bb)
- builder debug:
- { finished: \(finished), serializeDefaults: \(serializeDefaults), isNested: \(isNested) }
- """
+
+ public var debugDescription: String {
+ """
+ buffer debug:
+ \(_bb)
+ builder debug:
+ { finished: \(finished), serializeDefaults: \(serializeDefaults), isNested: \(isNested) }
+ """
+ }
+
+ /// VTableStorage is a class to contain the VTable buffer that would be serialized into buffer
+ @usableFromInline
+ internal class VTableStorage {
+ /// Memory check since deallocating each time we want to clear would be expensive
+ /// and memory leaks would happen if we dont deallocate the first allocated memory.
+ /// memory is promised to be available before adding `FieldLoc`
+ private var memoryInUse = false
+ /// Size of FieldLoc in memory
+ let size = MemoryLayout<FieldLoc>.stride
+ /// Memeory buffer
+ var memory: UnsafeMutableRawBufferPointer!
+ /// Capacity of the current buffer
+ var capacity: Int = 0
+ /// Maximuim offset written to the class
+ var maxOffset: VOffset = 0
+ /// number of fields written into the buffer
+ var numOfFields: Int = 0
+ /// Last written Index
+ var writtenIndex: Int = 0
+ /// the amount of added elements into the buffer
+ var addedElements: Int { capacity - (numOfFields &* size) }
+
+ /// Creates the memory to store the buffer in
+ init() {
+ memory = UnsafeMutableRawBufferPointer.allocate(byteCount: 0, alignment: 0)
}
- /// VTableStorage is a class to contain the VTable buffer that would be serialized into buffer
- @usableFromInline internal class VTableStorage {
- /// Memory check since deallocating each time we want to clear would be expensive
- /// and memory leaks would happen if we dont deallocate the first allocated memory.
- /// memory is promised to be available before adding `FieldLoc`
- private var memoryInUse = false
- /// Size of FieldLoc in memory
- let size = MemoryLayout<FieldLoc>.stride
- /// Memeory buffer
- var memory: UnsafeMutableRawBufferPointer!
- /// Capacity of the current buffer
- var capacity: Int = 0
- /// Maximuim offset written to the class
- var maxOffset: VOffset = 0
- /// number of fields written into the buffer
- var numOfFields: Int = 0
- /// Last written Index
- var writtenIndex: Int = 0
- /// the amount of added elements into the buffer
- var addedElements: Int { return capacity - (numOfFields &* size) }
-
- /// Creates the memory to store the buffer in
- init() {
- memory = UnsafeMutableRawBufferPointer.allocate(byteCount: 0, alignment: 0)
- }
-
- deinit {
- memory.deallocate()
- }
-
- /// Builds a buffer with byte count of fieldloc.size * count of field numbers
- /// - Parameter count: number of fields to be written
- func start(count: Int) {
- assert(count >= 0, "number of fields should NOT be negative")
- let capacity = count &* size
- ensure(space: capacity)
- }
-
- /// Adds a FieldLoc into the buffer, which would track how many have been written,
- /// and max offset
- /// - Parameter loc: Location of encoded element
- func add(loc: FieldLoc) {
- memory.baseAddress?.advanced(by: writtenIndex).storeBytes(of: loc, as: FieldLoc.self)
- writtenIndex = writtenIndex &+ size
- numOfFields = numOfFields &+ 1
- maxOffset = max(loc.position, maxOffset)
- }
-
- /// Clears the data stored related to the encoded buffer
- func clear() {
- maxOffset = 0
- numOfFields = 0
- writtenIndex = 0
- }
-
- /// Ensure that the buffer has enough space instead of recreating the buffer each time.
- /// - Parameter space: space required for the new vtable
- func ensure(space: Int) {
- guard space &+ writtenIndex > capacity else { return }
- memory.deallocate()
- memory = UnsafeMutableRawBufferPointer.allocate(byteCount: space, alignment: size)
- capacity = space
- }
+ deinit {
+ memory.deallocate()
+ }
- /// Loads an object of type `FieldLoc` from buffer memory
- /// - Parameter index: index of element
- /// - Returns: a FieldLoc at index
- func load(at index: Int) -> FieldLoc {
- return memory.load(fromByteOffset: index, as: FieldLoc.self)
- }
-
+ /// Builds a buffer with byte count of fieldloc.size * count of field numbers
+ /// - Parameter count: number of fields to be written
+ func start(count: Int) {
+ assert(count >= 0, "number of fields should NOT be negative")
+ let capacity = count &* size
+ ensure(space: capacity)
}
-
- internal struct FieldLoc {
- var offset: UOffset
- var position: VOffset
+
+ /// Adds a FieldLoc into the buffer, which would track how many have been written,
+ /// and max offset
+ /// - Parameter loc: Location of encoded element
+ func add(loc: FieldLoc) {
+ memory.baseAddress?.advanced(by: writtenIndex).storeBytes(of: loc, as: FieldLoc.self)
+ writtenIndex = writtenIndex &+ size
+ numOfFields = numOfFields &+ 1
+ maxOffset = max(loc.position, maxOffset)
}
+ /// Clears the data stored related to the encoded buffer
+ func clear() {
+ maxOffset = 0
+ numOfFields = 0
+ writtenIndex = 0
+ }
+
+ /// Ensure that the buffer has enough space instead of recreating the buffer each time.
+ /// - Parameter space: space required for the new vtable
+ func ensure(space: Int) {
+ guard space &+ writtenIndex > capacity else { return }
+ memory.deallocate()
+ memory = UnsafeMutableRawBufferPointer.allocate(byteCount: space, alignment: size)
+ capacity = space
+ }
+
+ /// Loads an object of type `FieldLoc` from buffer memory
+ /// - Parameter index: index of element
+ /// - Returns: a FieldLoc at index
+ func load(at index: Int) -> FieldLoc {
+ memory.load(fromByteOffset: index, as: FieldLoc.self)
+ }
+
+ }
+
+ internal struct FieldLoc {
+ var offset: UOffset
+ var position: VOffset
+ }
+
}
diff --git a/swift/Sources/FlatBuffers/FlatBufferObject.swift b/swift/Sources/FlatBuffers/FlatBufferObject.swift
index 52ca396..7536c40 100644
--- a/swift/Sources/FlatBuffers/FlatBufferObject.swift
+++ b/swift/Sources/FlatBuffers/FlatBufferObject.swift
@@ -1,15 +1,31 @@
+/*
+ * Copyright 2020 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 Foundation
/// FlatbufferObject structures all the Flatbuffers objects
public protocol FlatBufferObject {
- var __buffer: ByteBuffer! { get }
- init(_ bb: ByteBuffer, o: Int32)
+ var __buffer: ByteBuffer! { get }
+ init(_ bb: ByteBuffer, o: Int32)
}
public protocol ObjectAPI {
- associatedtype T
- static func pack(_ builder: inout FlatBufferBuilder, obj: inout T) -> Offset<UOffset>
- mutating func unpack() -> T
+ associatedtype T
+ static func pack(_ builder: inout FlatBufferBuilder, obj: inout T) -> Offset<UOffset>
+ mutating func unpack() -> T
}
/// Readable is structures all the Flatbuffers structs
@@ -17,12 +33,12 @@
/// Readable is a procotol that each Flatbuffer struct should confirm to since
/// FlatBufferBuilder would require a Type to both create(struct:) and createVector(structs:) functions
public protocol Readable: FlatBufferObject {
- static var size: Int { get }
- static var alignment: Int { get }
+ static var size: Int { get }
+ static var alignment: Int { get }
}
public protocol Enum {
- associatedtype T: Scalar
- static var byteSize: Int { get }
- var value: T { get }
+ associatedtype T: Scalar
+ static var byteSize: Int { get }
+ var value: T { get }
}
diff --git a/swift/Sources/FlatBuffers/FlatBuffersUtils.swift b/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
index 6838f86..507ef67 100644
--- a/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
+++ b/swift/Sources/FlatBuffers/FlatBuffersUtils.swift
@@ -1,16 +1,32 @@
+/*
+ * Copyright 2020 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 Foundation
public final class FlatBuffersUtils {
-
- /// Gets the size of the prefix
- /// - Parameter bb: Flatbuffer object
- public static func getSizePrefix(bb: ByteBuffer) -> Int32 {
- return bb.read(def: Int32.self, position: bb.reader)
- }
-
- /// Removes the prefix by duplicating the Flatbuffer
- /// - Parameter bb: Flatbuffer object
- public static func removeSizePrefix(bb: ByteBuffer) -> ByteBuffer {
- return bb.duplicate(removing: MemoryLayout<Int32>.size)
- }
+
+ /// Gets the size of the prefix
+ /// - Parameter bb: Flatbuffer object
+ public static func getSizePrefix(bb: ByteBuffer) -> Int32 {
+ bb.read(def: Int32.self, position: bb.reader)
+ }
+
+ /// Removes the prefix by duplicating the Flatbuffer
+ /// - Parameter bb: Flatbuffer object
+ public static func removeSizePrefix(bb: ByteBuffer) -> ByteBuffer {
+ bb.duplicate(removing: MemoryLayout<Int32>.size)
+ }
}
diff --git a/swift/Sources/FlatBuffers/Int+extension.swift b/swift/Sources/FlatBuffers/Int+extension.swift
index e52bdab..ed68ca0 100644
--- a/swift/Sources/FlatBuffers/Int+extension.swift
+++ b/swift/Sources/FlatBuffers/Int+extension.swift
@@ -1,31 +1,47 @@
+/*
+ * Copyright 2020 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 Foundation
extension Int {
-
- /// Moves the current int into the nearest power of two
- ///
- /// This is used since the UnsafeMutableRawPointer will face issues when writing/reading
- /// if the buffer alignment exceeds that actual size of the buffer
- var convertToPowerofTwo: Int {
- guard self > 0 else { return 1 }
- var n = UOffset(self)
-
- #if arch(arm) || arch(i386)
- let max = UInt32(Int.max)
- #else
- let max = UInt32.max
- #endif
-
- n -= 1
- n |= n >> 1
- n |= n >> 2
- n |= n >> 4
- n |= n >> 8
- n |= n >> 16
- if n != max {
- n += 1
- }
- return Int(n)
+ /// Moves the current int into the nearest power of two
+ ///
+ /// This is used since the UnsafeMutableRawPointer will face issues when writing/reading
+ /// if the buffer alignment exceeds that actual size of the buffer
+ var convertToPowerofTwo: Int {
+ guard self > 0 else { return 1 }
+ var n = UOffset(self)
+
+ #if arch(arm) || arch(i386)
+ let max = UInt32(Int.max)
+ #else
+ let max = UInt32.max
+ #endif
+
+ n -= 1
+ n |= n >> 1
+ n |= n >> 2
+ n |= n >> 4
+ n |= n >> 8
+ n |= n >> 16
+ if n != max {
+ n += 1
}
+
+ return Int(n)
+ }
}
diff --git a/swift/Sources/FlatBuffers/Message.swift b/swift/Sources/FlatBuffers/Message.swift
index 590d3d7..d1db357 100644
--- a/swift/Sources/FlatBuffers/Message.swift
+++ b/swift/Sources/FlatBuffers/Message.swift
@@ -1,41 +1,59 @@
+/*
+ * Copyright 2020 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.
+ */
+
public protocol FlatBufferGRPCMessage {
-
- /// Raw pointer which would be pointing to the beginning of the readable bytes
- var rawPointer: UnsafeMutableRawPointer { get }
-
- /// Size of readable bytes in the buffer
- var size: Int { get }
-
- init(byteBuffer: ByteBuffer)
+
+ /// Raw pointer which would be pointing to the beginning of the readable bytes
+ var rawPointer: UnsafeMutableRawPointer { get }
+
+ /// Size of readable bytes in the buffer
+ var size: Int { get }
+
+ init(byteBuffer: ByteBuffer)
}
/// Message is a wrapper around Buffers to to able to send Flatbuffers `Buffers` through the
/// GRPC library
public final class Message<T: FlatBufferObject>: FlatBufferGRPCMessage {
- internal var buffer: ByteBuffer
-
- /// Returns the an object of type T that would be read from the buffer
- public var object: T {
- T.init(buffer, o: Int32(buffer.read(def: UOffset.self, position: buffer.reader)) + Int32(buffer.reader))
- }
-
- public var rawPointer: UnsafeMutableRawPointer { return buffer.memory.advanced(by: buffer.reader) }
-
- public var size: Int { return Int(buffer.size) }
-
- /// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over
- /// GRPC
- /// - Parameter byteBuffer: Flatbuffer ByteBuffer object
- public init(byteBuffer: ByteBuffer) {
- buffer = byteBuffer
- }
-
- /// Initializes the message by copying the buffer to the message to be sent.
- /// from the builder
- /// - Parameter builder: FlatbufferBuilder that has the bytes created in
- /// - Note: Use `builder.finish(offset)` before passing the builder without prefixing anything to it
- public init(builder: inout FlatBufferBuilder) {
- buffer = builder.sizedBuffer
- builder.clear()
- }
+ internal var buffer: ByteBuffer
+
+ /// Returns the an object of type T that would be read from the buffer
+ public var object: T {
+ T.init(
+ buffer,
+ o: Int32(buffer.read(def: UOffset.self, position: buffer.reader)) + Int32(buffer.reader))
+ }
+
+ public var rawPointer: UnsafeMutableRawPointer { buffer.memory.advanced(by: buffer.reader) }
+
+ public var size: Int { Int(buffer.size) }
+
+ /// Initializes the message with the type Flatbuffer.Bytebuffer that is transmitted over
+ /// GRPC
+ /// - Parameter byteBuffer: Flatbuffer ByteBuffer object
+ public init(byteBuffer: ByteBuffer) {
+ buffer = byteBuffer
+ }
+
+ /// Initializes the message by copying the buffer to the message to be sent.
+ /// from the builder
+ /// - Parameter builder: FlatbufferBuilder that has the bytes created in
+ /// - Note: Use `builder.finish(offset)` before passing the builder without prefixing anything to it
+ public init(builder: inout FlatBufferBuilder) {
+ buffer = builder.sizedBuffer
+ builder.clear()
+ }
}
diff --git a/swift/Sources/FlatBuffers/Mutable.swift b/swift/Sources/FlatBuffers/Mutable.swift
index 90c1d8b..adcaa1f 100644
--- a/swift/Sources/FlatBuffers/Mutable.swift
+++ b/swift/Sources/FlatBuffers/Mutable.swift
@@ -1,67 +1,83 @@
+/*
+ * Copyright 2020 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 Foundation
/// Mutable is a protocol that allows us to mutate Scalar values within the buffer
public protocol Mutable {
- /// makes Flatbuffer accessed within the Protocol
- var bb: ByteBuffer { get }
- /// makes position of the table/struct accessed within the Protocol
- var postion: Int32 { get }
+ /// makes Flatbuffer accessed within the Protocol
+ var bb: ByteBuffer { get }
+ /// makes position of the table/struct accessed within the Protocol
+ var postion: Int32 { get }
}
extension Mutable {
-
- /// Mutates the memory in the buffer, this is only called from the access function of table and structs
- /// - Parameters:
- /// - value: New value to be inserted to the buffer
- /// - index: index of the Element
- func mutate<T: Scalar>(value: T, o: Int32) -> Bool {
- guard o != 0 else { return false }
- bb.write(value: value, index: Int(o), direct: true)
- return true
- }
+
+ /// Mutates the memory in the buffer, this is only called from the access function of table and structs
+ /// - Parameters:
+ /// - value: New value to be inserted to the buffer
+ /// - index: index of the Element
+ func mutate<T: Scalar>(value: T, o: Int32) -> Bool {
+ guard o != 0 else { return false }
+ bb.write(value: value, index: Int(o), direct: true)
+ return true
+ }
}
extension Mutable where Self == Table {
-
- /// Mutates a value by calling mutate with respect to the position in the table
- /// - Parameters:
- /// - value: New value to be inserted to the buffer
- /// - index: index of the Element
- public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
- guard index != 0 else { return false }
- return mutate(value: value, o: index + postion)
- }
-
- /// Directly mutates the element by calling mutate
- ///
- /// Mutates the Element at index ignoring the current position by calling mutate
- /// - Parameters:
- /// - value: New value to be inserted to the buffer
- /// - index: index of the Element
- public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
- return mutate(value: value, o: index)
- }
+
+ /// Mutates a value by calling mutate with respect to the position in the table
+ /// - Parameters:
+ /// - value: New value to be inserted to the buffer
+ /// - index: index of the Element
+ public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
+ guard index != 0 else { return false }
+ return mutate(value: value, o: index + postion)
+ }
+
+ /// Directly mutates the element by calling mutate
+ ///
+ /// Mutates the Element at index ignoring the current position by calling mutate
+ /// - Parameters:
+ /// - value: New value to be inserted to the buffer
+ /// - index: index of the Element
+ public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
+ mutate(value: value, o: index)
+ }
}
extension Mutable where Self == Struct {
-
- /// Mutates a value by calling mutate with respect to the position in the struct
- /// - Parameters:
- /// - value: New value to be inserted to the buffer
- /// - index: index of the Element
- public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
- return mutate(value: value, o: index + postion)
- }
-
- /// Directly mutates the element by calling mutate
- ///
- /// Mutates the Element at index ignoring the current position by calling mutate
- /// - Parameters:
- /// - value: New value to be inserted to the buffer
- /// - index: index of the Element
- public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
- return mutate(value: value, o: index)
- }
+
+ /// Mutates a value by calling mutate with respect to the position in the struct
+ /// - Parameters:
+ /// - value: New value to be inserted to the buffer
+ /// - index: index of the Element
+ public func mutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
+ mutate(value: value, o: index + postion)
+ }
+
+ /// Directly mutates the element by calling mutate
+ ///
+ /// Mutates the Element at index ignoring the current position by calling mutate
+ /// - Parameters:
+ /// - value: New value to be inserted to the buffer
+ /// - index: index of the Element
+ public func directMutate<T: Scalar>(_ value: T, index: Int32) -> Bool {
+ mutate(value: value, o: index)
+ }
}
extension Struct: Mutable {}
diff --git a/swift/Sources/FlatBuffers/NativeTable.swift b/swift/Sources/FlatBuffers/NativeTable.swift
index 057b376..5c844c1 100644
--- a/swift/Sources/FlatBuffers/NativeTable.swift
+++ b/swift/Sources/FlatBuffers/NativeTable.swift
@@ -1,29 +1,45 @@
+/*
+ * Copyright 2020 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 Foundation
public protocol NativeTable {}
extension NativeTable {
-
- /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly th
- /// - Parameter type: Type of the Flatbuffer object
- /// - Returns: returns the encoded sized ByteBuffer
- public func serialize<T: ObjectAPI>(type: T.Type) -> ByteBuffer where T.T == Self {
- var builder = FlatBufferBuilder(initialSize: 1024)
- return serialize(builder: &builder, type: type.self)
- }
-
- /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly.
- ///
- /// - Parameters:
- /// - builder: A FlatBufferBuilder
- /// - type: Type of the Flatbuffer object
- /// - Returns: returns the encoded sized ByteBuffer
- /// - Note: The `serialize(builder:type)` can be considered as a function that allows you to create smaller builder instead of the default `1024`.
- /// It can be considered less expensive in terms of memory allocation
- public func serialize<T: ObjectAPI>(builder: inout FlatBufferBuilder, type: T.Type) -> ByteBuffer where T.T == Self {
- var s = self
- let root = type.pack(&builder, obj: &s)
- builder.finish(offset: root)
- return builder.sizedBuffer
- }
+
+ /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly th
+ /// - Parameter type: Type of the Flatbuffer object
+ /// - Returns: returns the encoded sized ByteBuffer
+ public func serialize<T: ObjectAPI>(type: T.Type) -> ByteBuffer where T.T == Self {
+ var builder = FlatBufferBuilder(initialSize: 1024)
+ return serialize(builder: &builder, type: type.self)
+ }
+
+ /// Serialize is a helper function that serailizes the data from the Object API to a bytebuffer directly.
+ ///
+ /// - Parameters:
+ /// - builder: A FlatBufferBuilder
+ /// - type: Type of the Flatbuffer object
+ /// - Returns: returns the encoded sized ByteBuffer
+ /// - Note: The `serialize(builder:type)` can be considered as a function that allows you to create smaller builder instead of the default `1024`.
+ /// It can be considered less expensive in terms of memory allocation
+ public func serialize<T: ObjectAPI>(builder: inout FlatBufferBuilder, type: T.Type) -> ByteBuffer where T.T == Self {
+ var s = self
+ let root = type.pack(&builder, obj: &s)
+ builder.finish(offset: root)
+ return builder.sizedBuffer
+ }
}
diff --git a/swift/Sources/FlatBuffers/Offset.swift b/swift/Sources/FlatBuffers/Offset.swift
index cdb0227..4b42b04 100644
--- a/swift/Sources/FlatBuffers/Offset.swift
+++ b/swift/Sources/FlatBuffers/Offset.swift
@@ -1,12 +1,28 @@
+/*
+ * Copyright 2020 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 Foundation
/// Offset object for all the Objects that are written into the buffer
public struct Offset<T> {
- /// Offset of the object in the buffer
- public var o: UOffset
- /// Returns false if the offset is equal to zero
- public var isEmpty: Bool { return o == 0 }
-
- public init(offset: UOffset) { o = offset }
- public init() { o = 0 }
+ /// Offset of the object in the buffer
+ public var o: UOffset
+ /// Returns false if the offset is equal to zero
+ public var isEmpty: Bool { o == 0 }
+
+ public init(offset: UOffset) { o = offset }
+ public init() { o = 0 }
}
diff --git a/swift/Sources/FlatBuffers/Struct.swift b/swift/Sources/FlatBuffers/Struct.swift
index 88e3a41..73b3295 100644
--- a/swift/Sources/FlatBuffers/Struct.swift
+++ b/swift/Sources/FlatBuffers/Struct.swift
@@ -1,16 +1,32 @@
+/*
+ * Copyright 2020 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 Foundation
public struct Struct {
- public private(set) var bb: ByteBuffer
- public private(set) var postion: Int32
-
- public init(bb: ByteBuffer, position: Int32 = 0) {
- self.bb = bb
- self.postion = position
- }
-
- public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
- let r = bb.read(def: T.self, position: Int(o + postion))
- return r
- }
+ public private(set) var bb: ByteBuffer
+ public private(set) var postion: Int32
+
+ public init(bb: ByteBuffer, position: Int32 = 0) {
+ self.bb = bb
+ postion = position
+ }
+
+ public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
+ let r = bb.read(def: T.self, position: Int(o + postion))
+ return r
+ }
}
diff --git a/swift/Sources/FlatBuffers/Table.swift b/swift/Sources/FlatBuffers/Table.swift
index 0f783bf..451398c 100644
--- a/swift/Sources/FlatBuffers/Table.swift
+++ b/swift/Sources/FlatBuffers/Table.swift
@@ -1,144 +1,166 @@
+/*
+ * Copyright 2020 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 Foundation
public struct Table {
- public private(set) var bb: ByteBuffer
- public private(set) var postion: Int32
-
- public init(bb: ByteBuffer, position: Int32 = 0) {
- guard isLitteEndian else {
- fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
- }
- self.bb = bb
- self.postion = position
- }
-
- public func offset(_ o: Int32) -> Int32 {
- let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
- return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(def: Int16.self, position: Int(vtable + o))) : 0
- }
-
- public func indirect(_ o: Int32) -> Int32 { return o + bb.read(def: Int32.self, position: Int(o)) }
+ public private(set) var bb: ByteBuffer
+ public private(set) var postion: Int32
- /// 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? {
- return directString(at: offset + postion)
+ public init(bb: ByteBuffer, position: Int32 = 0) {
+ guard isLitteEndian else {
+ fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
}
-
- /// Direct string reads from the buffer disregarding the position of the table.
- /// It would be preferable to use string unless the current position of the table is not needed
- /// - 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))
- let count = bb.read(def: Int32.self, position: Int(offset))
- let position = offset + Int32(MemoryLayout<Int32>.size)
- return bb.readString(at: position, count: count)
- }
-
- /// Reads from the buffer with respect to the position in the table.
- /// - Parameters:
- /// - type: Type of Scalar that needs to be read from the buffer
- /// - o: Offset of the Element
- public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
- return directRead(of: T.self, offset: o + postion)
- }
-
- /// Reads from the buffer disregarding the position of the table.
- /// It would be used when reading from an
- /// ```
- /// let offset = __t.offset(10)
- /// //Only used when the we already know what is the
- /// // position in the table since __t.vector(at:)
- /// // returns the index with respect to the position
- /// __t.directRead(of: Byte.self,
- /// offset: __t.vector(at: offset) + index * 1)
- /// ```
- /// - Parameters:
- /// - type: Type of Scalar that needs to be read from the buffer
- /// - o: Offset of the Element
- public func directRead<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
- let r = bb.read(def: T.self, position: Int(o))
- return r
- }
-
- public func union<T: FlatBufferObject>(_ o: Int32) -> T {
- let o = o + postion
- return directUnion(o)
- }
+ self.bb = bb
+ postion = position
+ }
- public func directUnion<T: FlatBufferObject>(_ o: Int32) -> T {
- return T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
- }
-
- public func getVector<T>(at off: Int32) -> [T]? {
- let o = offset(off)
- guard o != 0 else { return nil }
- return bb.readSlice(index: vector(at: o), count: vector(count: o))
- }
-
- /// 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 += postion
- o += bb.read(def: Int32.self, position: Int(o))
- return bb.read(def: Int32.self, position: Int(o))
- }
-
- /// Vector start index in the buffer
- /// - Parameter o:start offset of the vector
- /// - returns: the start index of the vector
- public func vector(at o: Int32) -> Int32 {
- var o = o
- o += postion
- return o + bb.read(def: Int32.self, position: Int(o)) + 4
- }
+ public func offset(_ o: Int32) -> Int32 {
+ let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
+ return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(
+ def: Int16.self,
+ position: Int(vtable + o))) : 0
+ }
+
+ public func indirect(_ o: Int32) -> Int32 { 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 + postion)
+ }
+
+ /// Direct string reads from the buffer disregarding the position of the table.
+ /// It would be preferable to use string unless the current position of the table is not needed
+ /// - 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))
+ let count = bb.read(def: Int32.self, position: Int(offset))
+ let position = offset + Int32(MemoryLayout<Int32>.size)
+ return bb.readString(at: position, count: count)
+ }
+
+ /// Reads from the buffer with respect to the position in the table.
+ /// - Parameters:
+ /// - type: Type of Scalar that needs to be read from the buffer
+ /// - o: Offset of the Element
+ public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
+ directRead(of: T.self, offset: o + postion)
+ }
+
+ /// Reads from the buffer disregarding the position of the table.
+ /// It would be used when reading from an
+ /// ```
+ /// let offset = __t.offset(10)
+ /// //Only used when the we already know what is the
+ /// // position in the table since __t.vector(at:)
+ /// // returns the index with respect to the position
+ /// __t.directRead(of: Byte.self,
+ /// offset: __t.vector(at: offset) + index * 1)
+ /// ```
+ /// - Parameters:
+ /// - type: Type of Scalar that needs to be read from the buffer
+ /// - o: Offset of the Element
+ public func directRead<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
+ let r = bb.read(def: T.self, position: Int(o))
+ return r
+ }
+
+ public func union<T: FlatBufferObject>(_ o: Int32) -> T {
+ let o = o + postion
+ return directUnion(o)
+ }
+
+ public func directUnion<T: FlatBufferObject>(_ o: Int32) -> T {
+ T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
+ }
+
+ public func getVector<T>(at off: Int32) -> [T]? {
+ let o = offset(off)
+ guard o != 0 else { return nil }
+ return bb.readSlice(index: vector(at: o), count: vector(count: o))
+ }
+
+ /// 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 += postion
+ o += bb.read(def: Int32.self, position: Int(o))
+ return bb.read(def: Int32.self, position: Int(o))
+ }
+
+ /// Vector start index in the buffer
+ /// - Parameter o:start offset of the vector
+ /// - returns: the start index of the vector
+ public func vector(at o: Int32) -> Int32 {
+ var o = o
+ o += postion
+ return o + bb.read(def: Int32.self, position: Int(o)) + 4
+ }
}
extension Table {
-
- static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { return o + fbb.read(def: Int32.self, position: Int(o)) }
-
- 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)))))
+
+ static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { o + fbb.read(
+ def: Int32.self,
+ position: Int(o)) }
+
+ 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)))))
+ }
+
+ 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)
+ }
}
-
- 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
+ return len1 - len2
+ }
+
+ 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 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))
+ }
}
-
- 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 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
- }
+ return len1 - len2
+ }
}