Skip to content

Commit

Permalink
#161 Add DataContainer
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Nov 4, 2024
1 parent c75bd63 commit a2825fb
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 46 deletions.
80 changes: 80 additions & 0 deletions Sources/Bluetooth/Data.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// DataContainer.swift
// Bluetooth
//
// Created by Alsey Coleman Miller on 11/4/24.
//

#if canImport(Foundation)
import Foundation
#endif

/// Data container type.
public protocol DataContainer: RandomAccessCollection where Self.Index == Int, Self.Element == UInt8, Self: Hashable {

init()

init<C: Collection> (_ collection: C) where C.Element == UInt8

mutating func reserveCapacity(_ capacity: Int)

subscript(index: Int) -> UInt8 { get }

mutating func append(_ newElement: UInt8)

mutating func append(_ pointer: UnsafePointer<UInt8>, count: Int)

mutating func append <C: Collection> (contentsOf bytes: C) where C.Element == UInt8

static func += (lhs: inout Self, rhs: UInt8)

static func += <C: Collection> (lhs: inout Self, rhs: C) where C.Element == UInt8

/// Return a new copy of the data in a specified range.
///
/// - parameter range: The range to copy.
func subdata(in range: Range<Index>) -> Self
}

#if canImport(Foundation)
extension Data: DataContainer {

public static func += (lhs: inout Data, rhs: UInt8) {
lhs.append(rhs)
}
}
#endif

extension LowEnergyAdvertisingData: DataContainer {

public mutating func reserveCapacity(_ capacity: Int) {
// does nothing
}

public func subdata(in range: Range<Int>) -> LowEnergyAdvertisingData {
var data = LowEnergyAdvertisingData()
for (newIndex, oldIndex) in range.enumerated() {
data[newIndex] = self[oldIndex]
}
return data
}
}

extension Array: DataContainer where Self.Element == UInt8 {

public static func += (lhs: inout Array<Element>, rhs: UInt8) {
lhs.append(rhs)
}

public mutating func append(_ pointer: UnsafePointer<UInt8>, count: Int) {
let newCapacity = self.count + count
self.reserveCapacity(newCapacity)
for index in 0 ..< count {
self.append(pointer[index])
}
}

public func subdata(in range: Range<Int>) -> [UInt8] {
.init(self[range])
}
}
51 changes: 10 additions & 41 deletions Sources/Bluetooth/Extensions/DataConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,24 @@ internal protocol DataConvertible {
var dataLength: Int { get }
}

#if canImport(Foundation)
extension Data {
extension DataContainer {

/// Initialize data with contents of value.
init <T: DataConvertible> (_ value: T) {
let length = value.dataLength
self.init(capacity: length)
self.init()
self.reserveCapacity(length)
self += value
assert(self.count == length)
}
}
#endif

extension DataContainer {

mutating func append <T: DataConvertible> (_ value: T) {
self += value
}
}

extension BluetoothUUID: DataConvertible {

Expand Down Expand Up @@ -94,40 +100,3 @@ extension UInt32: UnsafeDataConvertible { }
extension UInt64: UnsafeDataConvertible { }
extension UInt128: UnsafeDataConvertible { }
extension BluetoothAddress: UnsafeDataConvertible { }

// MARK: - DataContainer

/// Data container type.
@usableFromInline
internal protocol DataContainer: RandomAccessCollection where Self.Index == Int {

subscript(index: Int) -> UInt8 { get }

mutating func append(_ newElement: UInt8)

mutating func append(_ pointer: UnsafePointer<UInt8>, count: Int)

mutating func append <C: Collection> (contentsOf bytes: C) where C.Element == UInt8

static func += (lhs: inout Self, rhs: UInt8)
static func += <C: Collection> (lhs: inout Self, rhs: C) where C.Element == UInt8
}

extension DataContainer {

mutating func append <T: DataConvertible> (_ value: T) {
self += value
}
}

#if canImport(Foundation)
extension Data: DataContainer {

@usableFromInline
static func += (lhs: inout Data, rhs: UInt8) {
lhs.append(rhs)
}
}
#endif

extension LowEnergyAdvertisingData: DataContainer { }
7 changes: 2 additions & 5 deletions Sources/Bluetooth/LowEnergyAdvertisingData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,8 @@ public extension LowEnergyAdvertisingData {
}
}

init? <C: Collection> (_ collection: C) where C.Element == UInt8 {

guard collection.count <= 31
else { return nil }

init<C: Collection> (_ collection: C) where C.Element == UInt8 {
precondition(collection.count <= 31)
self.init()
self.length = UInt8(collection.count)
collection.enumerated().forEach {
Expand Down

0 comments on commit a2825fb

Please sign in to comment.