有没有办法在不复制的情况下将数据"cast"到 [UInt8](字节数组),还是不安全?



我知道我能做

//Setup
let originalBytes: [UInt8] = [0x0, 0x1, 0x2]
let originalData = Data(originalBytes)
//This
let getByteArFromData: [UInt8] = [UInt8](originalData)

现在,我非常确信getByteArFromData将字节复制到新分配的内存中(我错了吗?(。

随着数据的缩放(例如图像、编解码器操作等(,这会使变得昂贵

我之所以提出这个问题,是因为我想通过一个类似数组的接口来操作数据,但据我所知,不安全的API是可行的。所以…

使用不安全的API是唯一的方法吗?这是推荐的方法吗?

我也玩过一些指针运算(只是进入了不安全的API,不确定如果我可以使用类似数组的接口,我是否应该投入时间(。

这里有一些操场代码(如果你愿意的话,请批评它并回答评论中的问题(:

import Foundation
//MARK:- Setup
final class PlaygroundSwingSet
{
//Squish unimportant setup code
private let byteAr: [UInt8]
private lazy var data: Data = {Data(byteAr)}()
init(_ bytes: [UInt8]) {self.byteAr = bytes}
func swing() -> Int
{
//Unsafe API stuff
return data.withUnsafeBytes {(dataBufferPtr) -> (Int) in   //No need for [weak self], right?
//I don't like how the pointers are only valid in this closure.
//It adds an indent to my code to which my "code OCD" forces me to abstract out
self.middleOut(dataBufferPtr)
}
}
private func middleOut(_ dataBufferPtr: UnsafeRawBufferPointer) -> Int
{
//Yuck, I have to make sure count isn't 0 AND safely unwrap.
//Why is .baseAddress even optional then?
guard let dataPtr = dataBufferPtr.baseAddress?.assumingMemoryBound(to: UInt8.self), dataBufferPtr.count > 0 else {
print("data is empty")
return 0
}
let middishIndex = dataBufferPtr.count / 2 - 1
//More yuck.
print("truncated middle element's value is (dataPtr.advanced(by: middishIndex).pointee)")
print("this should yield the same thing: ((dataPtr + middishIndex).pointee)")
return middishIndex
}
}
//MARK:- Code Execution
let a = PlaygroundSwingSet([0x1, 0x2, 0x3, 0x4]).swing() //a = 1
//Console prints
/*
truncated middle element's value is 3
this should yield the same thing: 2
*/
let b = PlaygroundSwingSet([]).swing()  //b = 0
//Console prints
/*
data is empty
*/

不需要强制转换Data,因为它支持下标运算符访问给定索引处的UInt8

顺便说一句,它还支持isEmpty,所以您不需要检查count是否为0。

var data = Data(repeating: 0, count: 5)
data.indices.forEach { data[$0] = UInt8($0) }
print(data[2])

最新更新