I'd like to access the raw bytes in Data as an array of numeric types for quick parsing. I have lots of data to parse, so I'm looking for efficiency. Data is a mix of shorts, ints, longs, and doubles.
The below code seems to work and be fast, but I'm getting deprecated warning: 'withUnsafeBytes' is deprecated
I can't figure out the updated way to treat the underlying bytes as an array of numbers for quick lookup.
var data: Data = ...
// create "virtual" arrays of different types to directly access bytes (without copying bytes)
let ushortArray: [UInt16] = data.withUnsafeBytes {
[UInt16](UnsafeBufferPointer(start: $0, count: data.count/2))
}
let intArray: [Int32] = data.withUnsafeBytes {
[Int32](UnsafeBufferPointer(start: $0, count: data.count/4))
}
// Access data simply
var i1: UInt16 = ushortArray[0]
var i2: Int32 = intArray[1]
P.S. I'm not concerned with big/little endian
If you want to load it as an Array what you need is to use UnsafeRawBufferPointer
bindMemory
method to the type you want. you can also extend ContiguousBytes to make a generic method and simplify your syntax:
Note: if you are planing to get a subsequence of your data make sure to do NOT subscript the data to avoid misaligned errors. You need to use Data subdata method instead.
extension ContiguousBytes {
func objects<T>() -> [T] { withUnsafeBytes { .init($0.bindMemory(to: T.self)) } }
var uInt16Array: [UInt16] { objects() }
var int32Array: [Int32] { objects() }
}
extension Array {
var data: Data { withUnsafeBytes { .init($0) } }
}
Usage:
let uInt16Array: [UInt16] = [.min, 1, 2, 3, .max] // [0, 1, 2, 3, 65535]
let int32Array: [Int32] = [.min, 1, 2, 3, .max] // [-2147483648, 1, 2, 3, 2147483647]
let uInt16ArrayData = uInt16Array.data // 10 bytes
let int32ArrayData = int32Array.data // 20 bytes
let uInt16ArrayLoaded = uInt16ArrayData.uInt16Array // [0, 1, 2, 3, 65535]
let int32ArrayLoaded = int32ArrayData.int32Array // [-2147483648, 1, 2, 3, 2147483647]
// Access data simply
let i1 = uInt16ArrayLoaded[0] // UInt16 0
let i2 = int32ArrayLoaded[0] // Int32 -2147483648
let i3 = uInt16ArrayLoaded[4] // UInt16 65535
let i4 = int32ArrayLoaded[4] // Int32 2147483647