Reputation: 1178
How to convert swift's Int64
to UUID
and back? Since UUID
is 128 bit, I want to fill top 64 bits with zeroes.
I can construct UUID
from uuid_t
, which is a tuple of UInt8
, by shifting and casting Int64
eight times.
Is there a better way?
Upvotes: 1
Views: 5088
Reputation: 236275
You can also use withUnsafeBytes
and simply load it as UUID
:
let vals: [UInt64] = [0, 0x123456789abcdef]
let uuid = vals.withUnsafeBytes { $0.load(as: UUID.self) }
print(uuid) // 00000000-0000-0000-EFCD-AB8967452301
Upvotes: 0
Reputation: 7582
The "simplest" way to do it (without relying on the memory layout of CollectionType
or Tuple
, and doesn't need NSUUID
) is:
extension UUID {
init(number: Int64) {
var number = number
let numberData = Data(bytes: &number, count: MemoryLayout<Int64>.size)
let bytes = [UInt8](numberData)
let tuple: uuid_t = (0, 0, 0, 0, 0, 0, 0, 0,
bytes[0], bytes[1], bytes[2], bytes[3],
bytes[4], bytes[5], bytes[6], bytes[7])
self.init(uuid: tuple)
}
var intValue: Int64? {
let tuple = self.uuid
guard tuple.0 == 0 && tuple.1 == 0 && tuple.2 == 0 && tuple.3 == 0 &&
tuple.4 == 0 && tuple.5 == 0 && tuple.6 == 0 && tuple.7 == 0 else {
return nil
}
let bytes: [UInt8] = [tuple.8, tuple.9, tuple.10, tuple.11,
tuple.12, tuple.13, tuple.14, tuple.15]
let numberData = Data(bytes: bytes)
let number = numberData.withUnsafeBytes { $0.pointee } as Int64
return number
}
}
Also, you may want to throw
/fatalError
instead of returning nil
.
UUID
sFor completion sake (and to make it actually possible to create valid UUIDs) I added a way to create it from 2 Int64
and rewrote the answer to your question using that:
UUID
creation from (Int64, Int64)
extension UUID {
init(numbers: (Int64, Int64)) {
var firstNumber = numbers.0
var secondNumber = numbers.1
let firstData = Data(bytes: &firstNumber, count: MemoryLayout<Int64>.size)
let secondData = Data(bytes: &secondNumber, count: MemoryLayout<Int64>.size)
let bytes = [UInt8](firstData) + [UInt8](secondData)
let tuple: uuid_t = (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])
self.init(uuid: tuple)
}
var intTupleValue: (Int64, Int64) {
let tuple = self.uuid
let firstBytes: [UInt8] = [tuple.0, tuple.1, tuple.2, tuple.3,
tuple.4, tuple.5, tuple.6, tuple.7]
let secondBytes: [UInt8] = [tuple.8, tuple.9, tuple.10, tuple.11,
tuple.12, tuple.13, tuple.14, tuple.15]
let firstData = Data(bytes: firstBytes)
let secondData = Data(bytes: secondBytes)
let first = firstData.withUnsafeBytes { $0.pointee } as Int64
let second = secondData.withUnsafeBytes { $0.pointee } as Int64
return (first, second)
}
}
UUID
creation from Int64
(filling MSBs with 0s)extension UUID {
init(number: Int64) {
self.init(numbers: (0, number))
}
var intValue: Int64? {
let (first, second) = intTupleValue
guard first == 0 else { return nil }
return second
}
}
Upvotes: 4
Reputation: 539685
UUID
is the Swift overlay type for the Foundation type NSUUID
,
and the latter can be created from a byte buffer. With a little bit
of pointer juggling this works with 64-bit integers as well:
let vals: [UInt64] = [0, 0x123456789abcdef]
let uuid = vals.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: 16) {
NSUUID(uuidBytes: $0) as UUID
}
}
print(uuid) // 00000000-0000-0000-EFCD-AB8967452301
Upvotes: 3