Skip to content

Commit

Permalink
#161 Fix BluetoothGAP data serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Nov 5, 2024
1 parent 61961b7 commit 09fe776
Show file tree
Hide file tree
Showing 41 changed files with 303 additions and 221 deletions.
97 changes: 50 additions & 47 deletions Sources/BluetoothGAP/Decoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public struct GAPDataDecoder <Data: DataContainer> {

#if !hasFeature(Embedded)
/// initialize with default precomputed values
self.types = GAPDataDecoderCache.defaultTypes
self.dataTypes = GAPDataDecoderCache.defaultDataTypes
self.types = Self.defaultTypes
self.dataTypes = Self.defaultDataTypes
#endif
}

Expand Down Expand Up @@ -231,56 +231,59 @@ public enum GAPDataDecoderError: Swift.Error, Sendable {
// MARK: - Constants

#if !hasFeature(Embedded)
internal enum GAPDataDecoderCache {
internal extension GAPDataDecoder {

static let defaultDataTypes: [GAPDataType: GAPData.Type] = {
static var defaultDataTypes: [GAPDataType: GAPData.Type] {
let defaultTypes = self.defaultTypes
var types = [GAPDataType: GAPData.Type](minimumCapacity: defaultTypes.count)
defaultTypes.forEach { types[$0.dataType] = $0 }
return types
}()
}

static let defaultTypes: [GAPData.Type] = [
GAP3DInformation.self,
GAPAdvertisingInterval.self,
GAPAppearanceData.self,
GAPChannelMapUpdateIndication.self,
GAPClassOfDevice.self,
GAPCompleteListOf16BitServiceClassUUIDs.self,
GAPCompleteListOf32BitServiceClassUUIDs.self,
GAPCompleteListOf128BitServiceClassUUIDs.self,
GAPCompleteLocalName.self,
GAPFlags.self,
GAPIncompleteListOf16BitServiceClassUUIDs.self,
GAPIncompleteListOf32BitServiceClassUUIDs.self,
GAPIncompleteListOf128BitServiceClassUUIDs.self,
GAPIndoorPositioning.self,
GAPLEDeviceAddress.self,
GAPLERole.self,
GAPLESecureConnectionsConfirmation.self,
GAPLESecureConnectionsRandom.self,
//GAPLESupportedFeatures.self,
GAPListOf16BitServiceSolicitationUUIDs.self,
GAPListOf32BitServiceSolicitationUUIDs.self,
GAPListOf128BitServiceSolicitationUUIDs.self,
GAPManufacturerSpecificData.self,
GAPMeshBeacon.self,
GAPMeshMessage.self,
GAPPBADV.self,
GAPPublicTargetAddress.self,
GAPRandomTargetAddress.self,
GAPSecurityManagerOOBFlags.self,
GAPSecurityManagerTKValue.self,
GAPServiceData16BitUUID.self,
GAPServiceData32BitUUID.self,
GAPServiceData128BitUUID.self,
GAPShortLocalName.self,
GAPSimplePairingHashC.self,
GAPSimplePairingRandomizerR.self,
GAPSlaveConnectionIntervalRange.self,
GAPTransportDiscoveryData.self,
GAPTxPowerLevel.self,
GAPURI.self
]
static var defaultTypes: [GAPData.Type] {
[
GAP3DInformation.self,
GAPAdvertisingInterval.self,
GAPAppearanceData.self,
GAPChannelMapUpdateIndication.self,
GAPClassOfDevice.self,
GAPCompleteListOf16BitServiceClassUUIDs.self,
GAPCompleteListOf32BitServiceClassUUIDs.self,
GAPCompleteListOf128BitServiceClassUUIDs.self,
GAPCompleteLocalName.self,
GAPFlags.self,
GAPIncompleteListOf16BitServiceClassUUIDs.self,
GAPIncompleteListOf32BitServiceClassUUIDs.self,
GAPIncompleteListOf128BitServiceClassUUIDs.self,
GAPIndoorPositioning.self,
GAPLEDeviceAddress.self,
GAPLERole.self,
GAPLESecureConnectionsConfirmation.self,
GAPLESecureConnectionsRandom.self,
//GAPLESupportedFeatures.self,
GAPListOf16BitServiceSolicitationUUIDs.self,
GAPListOf32BitServiceSolicitationUUIDs.self,
GAPListOf128BitServiceSolicitationUUIDs.self,
GAPManufacturerSpecificData<Data>.self,
GAPMeshBeacon.self,
GAPMeshMessage.self,
GAPPBADV<Data>.self,
GAPPublicTargetAddress.self,
GAPRandomTargetAddress.self,
GAPSecurityManagerOOBFlags.self,
GAPSecurityManagerTKValue.self,
GAPServiceData16BitUUID<Data>.self,
GAPServiceData32BitUUID<Data>.self,
GAPServiceData128BitUUID<Data>.self,
GAPShortLocalName.self,
GAPSimplePairingHashC.self,
GAPSimplePairingRandomizerR.self,
GAPSlaveConnectionIntervalRange.self,
GAPTransportDiscoveryData<Data>.self,
GAPTxPowerLevel.self,
GAPURI.self
]
}
}
#endif

7 changes: 5 additions & 2 deletions Sources/BluetoothGAP/GAP3DInformation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/**
The 3DD shall include a section in its EIR data providing 3D Synchronization Profile
Expand Down Expand Up @@ -63,7 +66,7 @@ public struct GAP3DInformation: GAPData, Equatable {

public extension GAP3DInformation {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard data.count == 2
else { return nil }
Expand All @@ -74,7 +77,7 @@ public extension GAP3DInformation {
self.init(flags: flags, pathLossThreshold: pathLossThreshold)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += flags.rawValue
data += pathLossThreshold
Expand Down
7 changes: 5 additions & 2 deletions Sources/BluetoothGAP/GAPAdvertisingInterval.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// The Advertising Interval data type contains the `advInterval` value
/// as defined in the Core specification, Volume 6, Part B, Section 4.4.2.2.
Expand Down Expand Up @@ -38,7 +41,7 @@ public extension GAPAdvertisingInterval {

public extension GAPAdvertisingInterval {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard data.count == MemoryLayout<UInt16>.size
else { return nil }
Expand All @@ -48,7 +51,7 @@ public extension GAPAdvertisingInterval {
self.init(interval: interval)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += interval.littleEndian
}
Expand Down
7 changes: 5 additions & 2 deletions Sources/BluetoothGAP/GAPAppearanceData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// The Appearance data type defines the external appearance of the device.
/// This value shall be the same as the Appearance characteristic, as defined in Vol. 3, Part C, Section 12.2.
Expand All @@ -25,7 +28,7 @@ public struct GAPAppearanceData: GAPData, Equatable {

public extension GAPAppearanceData {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard data.count == 2
else { return nil }
Expand All @@ -35,7 +38,7 @@ public extension GAPAppearanceData {
self.init(appearance: appearance)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += appearance.rawValue.littleEndian
}
Expand Down
7 changes: 5 additions & 2 deletions Sources/BluetoothGAP/GAPChannelMapUpdateIndication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// The channel map (channelMap) used for periodic advertisements may be updated at any time by the advertiser.
/// The advertiser can update the channel map by sending the Channel Map Update Indication data type in the extended header of the packet containing the AUX_SYNC_IND PDU.
Expand All @@ -33,15 +36,15 @@ public extension GAPChannelMapUpdateIndication {

internal static let length = 7

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard data.count == type(of: self).length
else { return nil }

self.init(channelMap: (data[0], data[1], data[2], data[3], data[4]), instant: (data[5], data[6]))
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += [channelMap.0, channelMap.1, channelMap.2, channelMap.3, channelMap.4, instant.0, instant.1]
}
Expand Down
7 changes: 5 additions & 2 deletions Sources/BluetoothGAP/GAPClassOfDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// Specifies the class of the device
/// Size: 3 octets
Expand All @@ -27,7 +30,7 @@ public struct GAPClassOfDevice: GAPData {

public extension GAPClassOfDevice {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard data.count == MemoryLayout<Identifier>.size
else { return nil }
Expand All @@ -39,7 +42,7 @@ public extension GAPClassOfDevice {
self.init(device: device)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += device.0
data += device.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// GAP Complete List of 128-bit Service Class UUIDs
@frozen
Expand All @@ -24,15 +27,15 @@ public struct GAPCompleteListOf128BitServiceClassUUIDs: GAPData, Equatable {

public extension GAPCompleteListOf128BitServiceClassUUIDs {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard let list = GAPUUIDList<UInt128>(data: data)
else { return nil }

self.uuids = list.uuids.map(UUID.init)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += GAPUUIDList(uuids: uuids.map(UInt128.init))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// GAP Complete List of 16-bit Service Class UUIDs
@frozen
Expand All @@ -24,15 +27,15 @@ public struct GAPCompleteListOf16BitServiceClassUUIDs: GAPData, Equatable {

public extension GAPCompleteListOf16BitServiceClassUUIDs {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard let list = GAPUUIDList<ArrayLiteralElement>(data: data)
else { return nil }

self.uuids = list.uuids
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += GAPUUIDList(uuids: uuids)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// GAP Complete List of 32-bit Service Class UUIDs
@frozen
Expand All @@ -24,15 +27,15 @@ public struct GAPCompleteListOf32BitServiceClassUUIDs: GAPData, Equatable {

public extension GAPCompleteListOf32BitServiceClassUUIDs {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard let list = GAPUUIDList<ArrayLiteralElement>(data: data)
else { return nil }

self.uuids = list.uuids
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += GAPUUIDList(uuids: uuids)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// Copyright © 2018 PureSwift. All rights reserved.
//

#if canImport(Foundation)
import Foundation
#endif
import Bluetooth

/// GAP Incomplete List of 128-bit Service Class UUIDs
@frozen
Expand All @@ -24,15 +27,15 @@ public struct GAPIncompleteListOf128BitServiceClassUUIDs: GAPData, Equatable {

public extension GAPIncompleteListOf128BitServiceClassUUIDs {

init?(data: Data) {
init?<Data: DataContainer>(data: Data) {

guard let list = GAPUUIDList<UInt128>(data: data)
else { return nil }

self.uuids = list.uuids.map(UUID.init)
}

func append(to data: inout Data) {
func append<Data: DataContainer>(to data: inout Data) {

data += GAPUUIDList(uuids: uuids.map(UInt128.init))
}
Expand Down
Loading

0 comments on commit 09fe776

Please sign in to comment.