Skip to content

Instantly share code, notes, and snippets.

@dagronf
Last active April 29, 2024 21:56
Show Gist options
  • Save dagronf/bb1d42c5d28a25499c2e1aab9f60f6c6 to your computer and use it in GitHub Desktop.
Save dagronf/bb1d42c5d28a25499c2e1aab9f60f6c6 to your computer and use it in GitHub Desktop.
Swift UUID -> Data code extension
extension UUID {
/// Errors thrown
public enum LoadError: Error {
case invalidUUIDData
}
/// Returns the raw bytes of the UUID as a Data object.
///
/// Note that this method assumes a specific memory layout (the layout on the device calling the method)
/// and as such may not be portable to other systems.
public var uuidData: Data {
var tempUUID = self.uuid
return withUnsafePointer(to: &tempUUID) { rawUuidPtr in
let bytes = UnsafeRawPointer(rawUuidPtr).assumingMemoryBound(to: UInt8.self)
let capacity = MemoryLayout<uuid_t>.size
return Data(bytes: bytes, count: capacity)
}
}
/// Create a UUID object initialized with the bytes stored in the Data object
///
/// - Parameter uuidData: The data object containing the binary form of the uuid
/// - Returns: a UUID object initialized with the bytes stored in the Data object
/// - Throws: Throws LoadError.invalidUUIDData if there aren't enough bytes, or if a UUID could not be created
///
/// Note that this method assumes a specific memory layout (the layout on the device calling the method)
/// and as such may not be portable to other systems.
init(uuidData data: Data) throws {
guard data.count >= MemoryLayout<uuid_t>.size else {
throw LoadError.invalidUUIDData
}
let uuid: NSUUID = try data.withUnsafeBytes { rawBuffer in
guard let bytes = rawBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
throw LoadError.invalidUUIDData
}
return NSUUID(uuidBytes: bytes)
}
self = uuid as UUID
}
}
func testUUIDToFromData() {
let uuid = UUID()
let UIDS = uuid.uuidString
let bytes = uuid.uuidData
if let uuid2 = try? UUID(uuidData: bytes) {
let UIDS2 = uuid2.uuidString
XCTAssertEqual(UIDS, UIDS2)
}
else {
XCTAssert(false, "Unable to load UUID from bytes")
}
}
@dagronf
Copy link
Author

dagronf commented Mar 22, 2019

If transferring uuids between different systems, it might be better to use the string form of the uuid for storage and/or transmission

@lbwanghr
Copy link

Thanks for sharing, however I got a warning when I used your code snippet.

The code snippet:

      var nsUUID: NSUUID?
      data.withUnsafeBytes { rawBytes in
         nsUUID = NSUUID(uuidBytes: rawBytes)
      }

The warning:

'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead

After some tries, I found the modification below would work.

      var nsUUID: NSUUID?
      data.withUnsafeBytes { rawBytes in
         nsUUID = NSUUID(uuidBytes: rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self))
      }

Hope this comment will help others.

@dagronf
Copy link
Author

dagronf commented Apr 29, 2024

Thanks @lbwanghr, I've updated the sample with your changes and cleaned the interface a bit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment