From c36b49606141eebd84c54af4abfb17ff9ecce2a0 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 5 Nov 2024 23:05:34 -0500 Subject: [PATCH] #154 Improve `BluetoothAddress` Embedded Swift support --- Sources/Bluetooth/Address.swift | 8 ++- .../Bluetooth/Extensions/Hexadecimal.swift | 53 ++++++++++++------- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Sources/Bluetooth/Address.swift b/Sources/Bluetooth/Address.swift index a25c01c24..329922918 100644 --- a/Sources/Bluetooth/Address.swift +++ b/Sources/Bluetooth/Address.swift @@ -90,6 +90,11 @@ extension BluetoothAddress: RawRepresentable { /// Initialize a Bluetooth Address from its big endian string representation (e.g. `00:1A:7D:DA:71:13`). public init?(rawValue: String) { + self.init(rawValue) + } + + /// Initialize a Bluetooth Address from its big endian string representation (e.g. `00:1A:7D:DA:71:13`). + internal init?(_ rawValue: S) { // verify string length let characters = rawValue.utf8 @@ -107,8 +112,7 @@ extension BluetoothAddress: RawRepresentable { for (index, subsequence) in components.enumerated() { guard subsequence.count == 2, - let string = String(subsequence), - let byte = UInt8(hexadecimal: string) + let byte = UInt8(hexadecimal: subsequence) else { return nil } withUnsafeMutablePointer(to: &bytes) { diff --git a/Sources/Bluetooth/Extensions/Hexadecimal.swift b/Sources/Bluetooth/Extensions/Hexadecimal.swift index 231df0bf1..3513df0ed 100644 --- a/Sources/Bluetooth/Extensions/Hexadecimal.swift +++ b/Sources/Bluetooth/Extensions/Hexadecimal.swift @@ -32,30 +32,14 @@ internal extension Collection where Element: FixedWidthInteger { internal extension FixedWidthInteger { - init?(parse string: String, radix: Self) { + init?(parse string: S, radix: Self) { #if !hasFeature(Embedded) let string = string.uppercased() #endif - let digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".utf8 - var result = Self(0) - for character in string.utf8 { - if let stringIndex = digits.enumerated().first(where: { $0.element == character })?.offset { - let val = Self(stringIndex) - if val >= radix { - return nil - } - result = result * radix + val - } else { - return nil - } - } - self = result + self.init(utf8: string.utf8, radix: radix) } -} - -internal extension FixedWidthInteger { - init?(hexadecimal string: String) { + init?(hexadecimal string: S) { guard string.utf8.count == MemoryLayout.size * 2 else { return nil } @@ -68,6 +52,37 @@ internal extension FixedWidthInteger { self.init(string, radix: 16) #endif } + + init?(hexadecimal utf8: C) where C: Collection, C.Element == UInt8 { + guard utf8.count == MemoryLayout.size * 2 else { + return nil + } + guard let value = Self(utf8: utf8, radix: 16) else { + return nil + } + self.init(value) + } + + /// Expects uppercase UTF8 data. + init?(utf8: C, radix: Self) where C: Collection, C.Element == UInt8 { + #if !hasFeature(Embedded) && DEBUG + assert(String(decoding: utf8, as: UTF8.self) == String(decoding: utf8, as: UTF8.self).uppercased(), "Expected uppercase string") + #endif + let digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".utf8 + var result = Self(0) + for character in utf8 { + if let stringIndex = digits.enumerated().first(where: { $0.element == character })?.offset { + let val = Self(stringIndex) + if val >= radix { + return nil + } + result = result * radix + val + } else { + return nil + } + } + self = result + } } #if !hasFeature(Embedded)