Skip to content

Commit

Permalink
Offical Swift port for FlexBuffers
Browse files Browse the repository at this point in the history
This is the offical port for FlexBuffers within
swift, and it introcudes a Common Module where code
is shared between flatbuffers and flexbuffers.

Writing most supported values like maps, vectors,
nil and scalars into a flexbuffer buffer. And includes
tests to verify that its similar to cpp
  • Loading branch information
mustiikhalil committed Feb 15, 2025
1 parent 1380857 commit 1dd2f1e
Show file tree
Hide file tree
Showing 20 changed files with 2,345 additions and 104 deletions.
13 changes: 12 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,21 @@ let package = Package(
.library(
name: "FlatBuffers",
targets: ["FlatBuffers"]),
.library(
name: "FlexBuffers",
targets: ["FlexBuffers"]),
],
targets: [
.target(
name: "FlatBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlatBuffers"),
.target(
name: "FlexBuffers",
dependencies: ["Common"],
path: "swift/Sources/FlexBuffers"),
.target(
name: "Common",
dependencies: [],
path: "swift/Sources"),
path: "swift/Sources/Common"),
])
103 changes: 103 additions & 0 deletions swift/Sources/Common/Constants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import Foundation

/// A boolean to see if the system is littleEndian
public let isLitteEndian: Bool = {
let number: UInt32 = 0x12345678
return number == number.littleEndian
}()

/// Constant for the file id length
public let FileIdLength = 4

/// Protocol that All Scalars should conform to
///
/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
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 {
self as! Self.NumericValue
}
}

extension Double: Scalar {
public typealias NumericValue = UInt64

public var convertedEndian: UInt64 {
bitPattern.littleEndian
}
}

extension Float32: Scalar {
public typealias NumericValue = UInt32

public var convertedEndian: UInt32 {
bitPattern.littleEndian
}
}

extension Bool: Scalar {
public var convertedEndian: UInt8 {
self == true ? 1 : 0
}

public typealias NumericValue = UInt8
}

extension Int: Scalar {
public typealias NumericValue = Int
}

extension Int8: Scalar {
public typealias NumericValue = Int8
}

extension Int16: Scalar {
public typealias NumericValue = Int16
}

extension Int32: Scalar {
public typealias NumericValue = Int32
}

extension Int64: Scalar {
public typealias NumericValue = Int64
}

extension UInt8: Scalar {
public typealias NumericValue = UInt8
}

extension UInt16: Scalar {
public typealias NumericValue = UInt16
}

extension UInt32: Scalar {
public typealias NumericValue = UInt32
}

extension UInt64: Scalar {
public typealias NumericValue = UInt64
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ extension Int {
///
/// 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 {
public var convertToPowerofTwo: Int {
guard self > 0 else { return 1 }
var n = UOffset(self)
var n = UInt32(self)

#if arch(arm) || arch(i386)
let max = UInt32(Int.max)
Expand Down
29 changes: 29 additions & 0 deletions swift/Sources/Common/functions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import Foundation

/// 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
@inline(__always)
public func padding(
bufSize: UInt,
elementSize: UInt) -> UInt
{
((~bufSize) &+ 1) & (elementSize &- 1)
}
1 change: 1 addition & 0 deletions swift/Sources/FlatBuffers/ByteBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import Common
import Foundation

/// `ByteBuffer` is the interface that stores the data for a `Flatbuffers` object
Expand Down
109 changes: 27 additions & 82 deletions swift/Sources/FlatBuffers/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,9 @@
* limitations under the License.
*/

@_exported import Common
import Foundation

/// A boolean to see if the system is littleEndian
let isLitteEndian: Bool = {
let number: UInt32 = 0x12345678
return number == number.littleEndian
}()
/// Constant for the file id length
let FileIdLength = 4
/// Type aliases
public typealias Byte = UInt8
public typealias UOffset = UInt32
Expand All @@ -35,80 +29,31 @@ public let FlatBufferMaxSize = UInt32
/// Protocol that All Scalars should conform to
///
/// Scalar is used to conform all the numbers that can be represented in a FlatBuffer. It's used to write/read from the buffer.
public protocol Scalar: Equatable {
associatedtype NumericValue
var convertedEndian: NumericValue { get }
}

extension Scalar where Self: Verifiable {}

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 {
self as! Self.NumericValue
}
}

extension Double: Scalar, Verifiable {
public typealias NumericValue = UInt64

public var convertedEndian: UInt64 {
bitPattern.littleEndian
}
}

extension Float32: Scalar, Verifiable {
public typealias NumericValue = UInt32

public var convertedEndian: UInt32 {
bitPattern.littleEndian
}
}

extension Bool: Scalar, Verifiable {
public var convertedEndian: UInt8 {
self == true ? 1 : 0
}

public typealias NumericValue = UInt8
}

extension Int: Scalar, Verifiable {
public typealias NumericValue = Int
}

extension Int8: Scalar, Verifiable {
public typealias NumericValue = Int8
}

extension Int16: Scalar, Verifiable {
public typealias NumericValue = Int16
}

extension Int32: Scalar, Verifiable {
public typealias NumericValue = Int32
}

extension Int64: Scalar, Verifiable {
public typealias NumericValue = Int64
}

extension UInt8: Scalar, Verifiable {
public typealias NumericValue = UInt8
}

extension UInt16: Scalar, Verifiable {
public typealias NumericValue = UInt16
}

extension UInt32: Scalar, Verifiable {
public typealias NumericValue = UInt32
}

extension UInt64: Scalar, Verifiable {
public typealias NumericValue = UInt64
}

extension Scalar where Self: FixedWidthInteger {}

extension Double: Verifiable {}

extension Float32: Verifiable {}

extension Bool: Verifiable {}

extension Int: Verifiable {}

extension Int8: Verifiable {}

extension Int16: Verifiable {}

extension Int32: Verifiable {}

extension Int64: Verifiable {}

extension UInt8: Verifiable {}

extension UInt16: Verifiable {}

extension UInt32: Verifiable {}

extension UInt64: Verifiable {}

public func FlatBuffersVersion_25_2_10() {}
22 changes: 4 additions & 18 deletions swift/Sources/FlatBuffers/FlatBufferBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import Common
import Foundation

/// ``FlatBufferBuilder`` builds a `FlatBuffer` through manipulating its internal state.
Expand Down Expand Up @@ -343,19 +344,6 @@ public struct FlatBufferBuilder {
}
}

/// 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
@inline(__always)
@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
Expand All @@ -364,11 +352,9 @@ public struct FlatBufferBuilder {
@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))))
_bb.fill(padding: numericCast(padding(
bufSize: numericCast(_bb.size) &+ numericCast(len),
elementSize: numericCast(alignment))))
}

/// Prealigns the buffer before writting a new object into the buffer
Expand Down
1 change: 1 addition & 0 deletions swift/Sources/FlatBuffers/Table.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import Common
import Foundation

/// `Table` is a Flatbuffers object that can read,
Expand Down
Loading

0 comments on commit 1dd2f1e

Please sign in to comment.