这里不推荐使用的版本withUnsafeBytes
是将底层指针绑定到已知类型(Data.withUnsafeBytes<R, T>(_ body: (UnsafePointer<T>) throws -> R) rethrows -> R
)的版本。
首选替换是不以这种方式绑定的版本,并返回一个原始缓冲区指针(withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
);幸运的是,在这些之间转换只会改变你从指针中读取的方式:
extension Data {
func scanValueFromData<T>(start: Int = 0, invalid: T) -> (T, Int) {
let length = MemoryLayout<T>.size
guard self.count >= start + length else {
return (invalid, start + length)
}
return (self.subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) }, start + length)
}
}
使用您可以安全地从缓冲区中UnsafeRawBufferPointer.load(as:)
读取一个普通类型。T
(请注意,此方法调用非平凡类型是不安全的,但该方法的原始版本也是如此。)
如果您想进一步简化,可以避免重复start + length
:
func scanValueFromData<T>(start: Int = 0, invalid: T) -> (T, Int) {
let length = MemoryLayout<T>.size
var value = invalid
if count >= start + length {
value = subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) }
}
return (value, start + length)
}
甚至更短,以牺牲可读性为代价:
func scanValueFromData<T>(start: Int = 0, invalid: T) -> (T, Int) {
let length = MemoryLayout<T>.size
let value = count >= start + length ? subdata(in: start ..< start + length).withUnsafeBytes { $0.load(as: T.self) } : invalid
return (value, start + length)
}