diff --git a/Sources/Bluetooth/Data.swift b/Sources/Bluetooth/Data.swift index 9d7031110..9663a9c82 100644 --- a/Sources/Bluetooth/Data.swift +++ b/Sources/Bluetooth/Data.swift @@ -103,6 +103,14 @@ public extension DataConvertible { } } +public extension Array where Element: DataConvertible { + + /// Append data representation into buffer. + static func += (data: inout T, value: Self) { + value.forEach { data += $0 } + } +} + public extension DataContainer { /// Initialize data with contents of value. diff --git a/Sources/BluetoothGATT/Extensions/Data.swift b/Sources/BluetoothGATT/Extensions/Data.swift index 7d41711c8..f426c2f30 100644 --- a/Sources/BluetoothGATT/Extensions/Data.swift +++ b/Sources/BluetoothGATT/Extensions/Data.swift @@ -6,77 +6,15 @@ // Copyright © 2018 PureSwift. All rights reserved. // -import Foundation - -internal extension Data { - - @usableFromInline - func subdataNoCopy(in range: Range) -> Data { - - // stored in heap, can reuse buffer - if count > Data.inlineBufferSize { - - return withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in - Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: buffer.baseAddress!.advanced(by: range.lowerBound)), - count: range.count, - deallocator: .none) - } - - } else { - - // stored in stack, must copy - return subdata(in: range) - } - } - - @usableFromInline - func withUnsafeBytes (in range: Range, _ block: ((UnsafeRawBufferPointer) throws -> Result)) rethrows -> Result { - - return try withUnsafeBytes { - return try block(UnsafeRawBufferPointer(rebasing: $0[range])) - } - } - - @usableFromInline - func suffixNoCopy(from index: Int) -> Data { - return subdataNoCopy(in: index ..< count) - } +internal extension DataContainer { @usableFromInline - func suffixCheckingBounds(from start: Int) -> Data { + func suffixCheckingBounds(from start: Int) -> Self { if count > start { - return Data(suffix(from: start)) + return Self(suffix(from: start)) } else { - return Data() + return Self() } } } - -internal extension Data { - - /// Size of the inline buffer for `Foundation.Data` used in Swift 5. - /// - /// Used to determine wheather data is stored on stack or in heap. - @usableFromInline - static var inlineBufferSize: Int { - - // Keep up to date - // https://github.com/apple/swift/blob/aa3e5904f8ba8bf9ae06d96946774d171074f6e5/stdlib/public/Darwin/Foundation/Data.swift#L656 - // https://github.com/apple/swift-corelibs-foundation/blob/76068b8caf54f250a7be5336a7c6bb97f55469f8/Sources/Foundation/Data.swift#L649 - #if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le) - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) //len //enum - #elseif arch(i386) || arch(arm) - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8) //len //enum - #elseif os(watchOS) // arm64_32 - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) //len //enum - #else - #error("This architecture isn't known. Add it to the 32-bit or 64-bit line.") - #endif - - return MemoryLayout.size - } -} diff --git a/Sources/BluetoothGATT/Extensions/DataConvertible.swift b/Sources/BluetoothGATT/Extensions/DataConvertible.swift deleted file mode 100644 index 3f5007e44..000000000 --- a/Sources/BluetoothGATT/Extensions/DataConvertible.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// DataConvertible.swift -// Bluetooth -// -// Created by Alsey Coleman Miller on 8/24/18. -// Copyright © 2018 PureSwift. All rights reserved. -// - -import Foundation - -/// Can be converted into data. -internal protocol DataConvertible { - - /// Append data representation into buffer. - static func += (data: inout T, value: Self) - - /// Length of value when encoded into data. - var dataLength: Int { get } -} - -extension Data { - - /// Initialize data with contents of value. - init (_ value: T) { - let length = value.dataLength - self.init(capacity: length) - self += value - assert(self.count == length) - } -} - -extension BluetoothUUID: DataConvertible { - - /// Number of bytes to represent Bluetooth UUID. - internal enum Length: Int { - - case bit16 = 2 - case bit32 = 4 - case bit128 = 16 - } - - internal var length: Length { - - switch self { - case .bit16: return .bit16 - case .bit32: return .bit32 - case .bit128: return .bit128 - } - } - - @usableFromInline - var dataLength: Int { - return length.rawValue - } - - @usableFromInline - static func += (data: inout T, value: BluetoothUUID) { - switch value { - case let .bit16(value): data += value - case let .bit32(value): data += value - case let .bit128(value): data += value - } - } -} - -// MARK: - UnsafeDataConvertible - -/// Internal Data casting protocol -internal protocol UnsafeDataConvertible: DataConvertible { } - -extension UnsafeDataConvertible { - - @usableFromInline - var dataLength: Int { - return MemoryLayout.size - } - - /// Append data representation into buffer. - static func += (data: inout T, value: Self) { - withUnsafePointer(to: value) { - $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size) { - data.append($0, count: MemoryLayout.size) - } - } - } -} - -extension UInt16: UnsafeDataConvertible { } -extension UInt32: UnsafeDataConvertible { } -extension UInt64: UnsafeDataConvertible { } -extension UInt128: UnsafeDataConvertible { } -extension BluetoothAddress: UnsafeDataConvertible { } diff --git a/Sources/BluetoothGATT/Extensions/Hexadecimal.swift b/Sources/BluetoothGATT/Extensions/Hexadecimal.swift index fde1fcb8f..3c851afa2 100644 --- a/Sources/BluetoothGATT/Extensions/Hexadecimal.swift +++ b/Sources/BluetoothGATT/Extensions/Hexadecimal.swift @@ -9,12 +9,26 @@ internal extension FixedWidthInteger { func toHexadecimal() -> String { - - var string = String(self, radix: 16) - while string.utf8.count < (MemoryLayout.size * 2) { + let length = MemoryLayout.size * 2 + var string: String + #if hasFeature(Embedded) || (canImport(Darwin) && DEBUG) + string = "" + string.reserveCapacity(length) + self.bigEndian.bytes.forEach { byte in + string.append(String(format: "%02X", length: 2, byte)!) + } + #else // Linux and non-Embedded release builds use Swift StdLib + string = String(self, radix: 16, uppercase: true) + // Add Zero padding + while string.utf8.count < length { string = "0" + string } - return string.uppercased() + #endif + assert(string.utf8.count == length) + #if !hasFeature(Embedded) + assert(string == string.uppercased(), "String should be uppercased") + #endif + return string } } @@ -29,3 +43,58 @@ internal extension Collection where Element: FixedWidthInteger { return string } } + +internal extension FixedWidthInteger { + + init?(parse string: S, radix: Self) { + #if !hasFeature(Embedded) + let string = string.uppercased() + #endif + self.init(utf8: string.utf8, radix: radix) + } + + init?(hexadecimal string: S) { + guard string.utf8.count == MemoryLayout.size * 2 else { + return nil + } + #if hasFeature(Embedded) || DEBUG + guard let value = Self(parse: string, radix: 16) else { + return nil + } + self.init(value) + #else + 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 + } +} diff --git a/Sources/BluetoothGATT/Extensions/Integer.swift b/Sources/BluetoothGATT/Extensions/Integer.swift index 10bf4a8f1..6457741e9 100644 --- a/Sources/BluetoothGATT/Extensions/Integer.swift +++ b/Sources/BluetoothGATT/Extensions/Integer.swift @@ -6,19 +6,17 @@ // Copyright © 2015 PureSwift. All rights reserved. // -import Foundation +import Bluetooth internal extension UInt16 { /// Initializes value from two bytes. init(bytes: (UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt16.self) } - /// Converts to two bytes. + /// Converts to two bytes. var bytes: (UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8).self) } } @@ -27,13 +25,11 @@ internal extension UInt32 { /// Initializes value from four bytes. init(bytes: (UInt8, UInt8, UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt32.self) } /// Converts to four bytes. var bytes: (UInt8, UInt8, UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8, UInt8, UInt8).self) } } @@ -42,17 +38,24 @@ internal extension UInt64 { /// Initializes value from four bytes. init(bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt64.self) } /// Converts to eight bytes. var bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self) } } +internal extension BinaryInteger { + + @inlinable + var bytes: [UInt8] { + var mutableValueCopy = self + return withUnsafeBytes(of: &mutableValueCopy) { Array($0) } + } +} + internal extension UInt8 { /// Initialize a byte from 2 bit enums. @@ -76,60 +79,38 @@ internal extension UInt8 { internal extension UInt64 { /// The value of the characteristic is a bit mask implemented as an array of unsigned 8 bit integers. - init?(bitmaskArray data: Data) { + init?(bitmaskArray data: Data) { if data.count == MemoryLayout.size { - self = UInt64(littleEndian: UInt64(bytes: (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]))) - } else if data.count >= MemoryLayout.size { - let rawValue = UInt32(littleEndian: UInt32(bytes: (data[0], data[1], data[2], data[3]))) - self = UInt64(rawValue) - } else if data.count >= MemoryLayout.size { - let rawValue = UInt16(littleEndian: UInt16(bytes: (data[0], data[1]))) - self = UInt64(rawValue) - } else if data.count >= MemoryLayout.size { - let rawValue = data[0] - self = UInt64(rawValue) - } else { - return nil } } /// The value of the characteristic is a bit mask implemented as an array of unsigned 8 bit integers. - var bitmaskArray: Data { + var bitmaskArray: [UInt8] { if self <= numericCast(UInt8.max) { - - return Data([UInt8(self)]) - + return [UInt8]([UInt8(self)]) } else if self <= numericCast(UInt16.max) { - let bytes = UInt16(self).littleEndian.bytes - - return Data([bytes.0, bytes.1]) - + return [UInt8]([bytes.0, bytes.1]) } else if self <= numericCast(UInt32.max) { - let bytes = UInt32(self).littleEndian.bytes - - return Data([bytes.0, bytes.1, bytes.2, bytes.3]) - + return [UInt8]([bytes.0, bytes.1, bytes.2, bytes.3]) } else { - let bytes = self.littleEndian.bytes - - return Data([bytes.0, bytes.1, bytes.2, bytes.3, bytes.4, bytes.5, bytes.6, bytes.7]) + return [UInt8]([bytes.0, bytes.1, bytes.2, bytes.3, bytes.4, bytes.5, bytes.6, bytes.7]) } } } diff --git a/Sources/BluetoothGATT/Extensions/OptionSet.swift b/Sources/BluetoothGATT/Extensions/OptionSet.swift new file mode 100644 index 000000000..d0761df90 --- /dev/null +++ b/Sources/BluetoothGATT/Extensions/OptionSet.swift @@ -0,0 +1,30 @@ +// +// OptionSet.swift +// Bluetooth +// +// Created by Alsey Coleman Miller on 11/5/24. +// + +extension OptionSet { + @inline(never) + internal func buildDescription( + _ descriptions: [(Element, StaticString)] + ) -> String { + var copy = self + var result = "[" + + for (option, name) in descriptions { + if _slowPath(copy.contains(option)) { + result += name.description + copy.remove(option) + if !copy.isEmpty { result += ", " } + } + } + + if _slowPath(!copy.isEmpty) { + result += "\(Self.self)(rawValue: \(copy.rawValue))" + } + result += "]" + return result + } +} diff --git a/Sources/BluetoothGATT/Extensions/String.swift b/Sources/BluetoothGATT/Extensions/String.swift new file mode 100644 index 000000000..2180ee382 --- /dev/null +++ b/Sources/BluetoothGATT/Extensions/String.swift @@ -0,0 +1,52 @@ +// +// String.swift +// Bluetooth +// +// Created by Alsey Coleman Miller on 11/4/24. +// + +#if canImport(Darwin) +import Darwin +#endif + +internal extension String { + + /// Initialize from UTF8 data. + init?(utf8 data: Data) { + // Newer Darwin and other platforms use StdLib parsing + if #available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) { + self.init(validating: data, as: UTF8.self) + } else { + // Older Darwin uses Foundation + #if canImport(Foundation) + self.init(bytes: data, encoding: .utf8) + #else + #error("Darwin should have Foundation framework") + #endif + } + } + + #if hasFeature(Embedded) + // Can't use `CVarArg` in Embedded Swift + init?(format: String, length: Int, _ value: UInt8) { + var cString: [CChar] = .init(repeating: 0, count: length + 1) + guard _snprintf_uint8_t(&cString, cString.count, format, value) >= 0 else { + return nil + } + self.init(cString: cString) + } + #elseif canImport(Darwin) + init?(format: String, length: Int, _ value: T) { + var cString: [CChar] = .init(repeating: 0, count: length + 1) + guard snprintf(ptr: &cString, cString.count, format, value) >= 0 else { + return nil + } + self.init(cString: cString) + } + #endif +} + +#if hasFeature(Embedded) +@_silgen_name("snprintf") +internal func _snprintf_uint8_t(_ pointer: UnsafeMutablePointer, _ length: Int, _ format: UnsafePointer, _ arg: UInt8) -> Int32 +#endif diff --git a/Sources/BluetoothGATT/Extensions/UUID.swift b/Sources/BluetoothGATT/Extensions/UUID.swift deleted file mode 100644 index 47ec6754d..000000000 --- a/Sources/BluetoothGATT/Extensions/UUID.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// UUID.swift -// Bluetooth -// -// Created by Alsey Coleman Miller on 4/5/17. -// Copyright © 2017 PureSwift. All rights reserved. -// - -import Foundation - -internal extension UUID { - - static var length: Int { return 16 } - static var stringLength: Int { return 36 } - static var unformattedStringLength: Int { return 32 } -} - -internal extension UUID { // ByteValue - - typealias ByteValue = uuid_t - - static var bitWidth: Int { return 128 } - - @inline(__always) - init(bytes: uuid_t) { - - self.init(uuid: bytes) - } - - var bytes: uuid_t { - - @inline(__always) - get { return uuid } - - @inline(__always) - set { self = UUID(uuid: newValue) } - } -} - -internal extension UUID { - - init?(data: Data) { - - guard data.count == UUID.length else { return nil } - - self.init(bytes: (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15])) - } - - var data: Data { - - return Data([bytes.0, bytes.1, bytes.2, bytes.3, bytes.4, bytes.5, bytes.6, bytes.7, bytes.8, bytes.9, bytes.10, bytes.11, bytes.12, bytes.13, bytes.14, bytes.15]) - } -} diff --git a/Sources/BluetoothHCI/Extensions/Data.swift b/Sources/BluetoothHCI/Extensions/Data.swift deleted file mode 100644 index aeb000196..000000000 --- a/Sources/BluetoothHCI/Extensions/Data.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// Data.swift -// Bluetooth -// -// Created by Alsey Coleman Miller on 5/30/18. -// Copyright © 2018 PureSwift. All rights reserved. -// - -import Foundation - -internal extension Data { - - @usableFromInline - func subdataNoCopy(in range: Range) -> Data { - - // stored in heap, can reuse buffer - if count > Data.inlineBufferSize { - - return withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in - Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: buffer.baseAddress!.advanced(by: range.lowerBound)), - count: range.count, - deallocator: .none) - } - - } else { - - // stored in stack, must copy - return subdata(in: range) - } - } - - @usableFromInline - func withUnsafeBytes (in range: Range, _ block: ((UnsafeRawBufferPointer) throws -> Result)) rethrows -> Result { - - return try withUnsafeBytes { - return try block(UnsafeRawBufferPointer(rebasing: $0[range])) - } - } - - @usableFromInline - func suffixNoCopy(from index: Int) -> Data { - return subdataNoCopy(in: index ..< count) - } -} - -internal extension Data { - - /// Size of the inline buffer for `Foundation.Data` used in Swift 5. - /// - /// Used to determine wheather data is stored on stack or in heap. - @usableFromInline - static var inlineBufferSize: Int { - - // Keep up to date - // https://github.com/apple/swift/blob/aa3e5904f8ba8bf9ae06d96946774d171074f6e5/stdlib/public/Darwin/Foundation/Data.swift#L656 - // https://github.com/apple/swift-corelibs-foundation/blob/76068b8caf54f250a7be5336a7c6bb97f55469f8/Sources/Foundation/Data.swift#L649 - #if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le) - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) //len //enum - #elseif arch(i386) || arch(arm) - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8) //len //enum - #elseif os(watchOS) // arm64_32 - typealias Buffer = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) //len //enum - #else - #error("This architecture isn't known. Add it to the 32-bit or 64-bit line.") - #endif - - return MemoryLayout.size - } -} diff --git a/Sources/BluetoothHCI/Extensions/DataConvertible.swift b/Sources/BluetoothHCI/Extensions/DataConvertible.swift deleted file mode 100644 index 3f5007e44..000000000 --- a/Sources/BluetoothHCI/Extensions/DataConvertible.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// DataConvertible.swift -// Bluetooth -// -// Created by Alsey Coleman Miller on 8/24/18. -// Copyright © 2018 PureSwift. All rights reserved. -// - -import Foundation - -/// Can be converted into data. -internal protocol DataConvertible { - - /// Append data representation into buffer. - static func += (data: inout T, value: Self) - - /// Length of value when encoded into data. - var dataLength: Int { get } -} - -extension Data { - - /// Initialize data with contents of value. - init (_ value: T) { - let length = value.dataLength - self.init(capacity: length) - self += value - assert(self.count == length) - } -} - -extension BluetoothUUID: DataConvertible { - - /// Number of bytes to represent Bluetooth UUID. - internal enum Length: Int { - - case bit16 = 2 - case bit32 = 4 - case bit128 = 16 - } - - internal var length: Length { - - switch self { - case .bit16: return .bit16 - case .bit32: return .bit32 - case .bit128: return .bit128 - } - } - - @usableFromInline - var dataLength: Int { - return length.rawValue - } - - @usableFromInline - static func += (data: inout T, value: BluetoothUUID) { - switch value { - case let .bit16(value): data += value - case let .bit32(value): data += value - case let .bit128(value): data += value - } - } -} - -// MARK: - UnsafeDataConvertible - -/// Internal Data casting protocol -internal protocol UnsafeDataConvertible: DataConvertible { } - -extension UnsafeDataConvertible { - - @usableFromInline - var dataLength: Int { - return MemoryLayout.size - } - - /// Append data representation into buffer. - static func += (data: inout T, value: Self) { - withUnsafePointer(to: value) { - $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size) { - data.append($0, count: MemoryLayout.size) - } - } - } -} - -extension UInt16: UnsafeDataConvertible { } -extension UInt32: UnsafeDataConvertible { } -extension UInt64: UnsafeDataConvertible { } -extension UInt128: UnsafeDataConvertible { } -extension BluetoothAddress: UnsafeDataConvertible { } diff --git a/Sources/BluetoothHCI/Extensions/Integer.swift b/Sources/BluetoothHCI/Extensions/Integer.swift index 63ac05c88..3407f20b2 100644 --- a/Sources/BluetoothHCI/Extensions/Integer.swift +++ b/Sources/BluetoothHCI/Extensions/Integer.swift @@ -6,19 +6,15 @@ // Copyright © 2015 PureSwift. All rights reserved. // -import Foundation - internal extension UInt16 { /// Initializes value from two bytes. init(bytes: (UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt16.self) } - /// Converts to two bytes. + /// Converts to two bytes. var bytes: (UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8).self) } } @@ -27,13 +23,11 @@ internal extension UInt32 { /// Initializes value from four bytes. init(bytes: (UInt8, UInt8, UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt32.self) } /// Converts to four bytes. var bytes: (UInt8, UInt8, UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8, UInt8, UInt8).self) } } @@ -42,13 +36,20 @@ internal extension UInt64 { /// Initializes value from four bytes. init(bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)) { - self = unsafeBitCast(bytes, to: UInt64.self) } /// Converts to eight bytes. var bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) { - return unsafeBitCast(self, to: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8).self) } } + +internal extension BinaryInteger { + + @inlinable + var bytes: [UInt8] { + var mutableValueCopy = self + return withUnsafeBytes(of: &mutableValueCopy) { Array($0) } + } +} diff --git a/Sources/BluetoothHCI/Extensions/UUID.swift b/Sources/BluetoothHCI/Extensions/UUID.swift deleted file mode 100644 index 535bde5ea..000000000 --- a/Sources/BluetoothHCI/Extensions/UUID.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// UUID.swift -// Bluetooth -// -// Created by Alsey Coleman Miller on 4/5/17. -// Copyright © 2017 PureSwift. All rights reserved. -// - -import Foundation - -internal extension UUID { - - static var length: Int { return 16 } -} - -internal extension UUID { // ByteValue - - typealias ByteValue = uuid_t - - static var bitWidth: Int { return 128 } - - @inline(__always) - init(bytes: uuid_t) { - - self.init(uuid: bytes) - } - - var bytes: uuid_t { - - @inline(__always) - get { return uuid } - - @inline(__always) - set { self = UUID(uuid: newValue) } - } -} - -internal extension UUID { - - init?(data: Data) { - - guard data.count == UUID.length else { return nil } - - self.init(bytes: (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15])) - } - - var data: Data { - - return Data([bytes.0, bytes.1, bytes.2, bytes.3, bytes.4, bytes.5, bytes.6, bytes.7, bytes.8, bytes.9, bytes.10, bytes.11, bytes.12, bytes.13, bytes.14, bytes.15]) - } -}