【问题标题】:Are these memory functions the same for Swift 5 Conversion UnsafeBufferPointerSwift 5 Conversion UnsafeBufferPointer 的这些内存功能是否相同
【发布时间】:2019-09-27 20:48:17
【问题描述】:

我正在对我不太理解的代码进行一些 Swift 5 转换,这些代码来自以前的开发人员的遗留代码。我明白了:

'withUnsafeBytes' 已弃用:改用 withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R`

为:

func toArray<T>(type: T.Type) -> [T] {
    return self.withUnsafeBytes {
        [T](UnsafeBufferPointer(start: $0, count: self.count/MemoryLayout<T>.stride))
    }
}

我想用这个替换它,但我不确定它是否做同样的事情:

func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
    var array = [T](repeating: 0, count: self.count/MemoryLayout<T>.stride)
    _ = array.withUnsafeMutableBytes { copyBytes(to: $0) }
    return array
}

在这两个 fxs 的上下文中使用:

static func extractPacketSizeFromIV(iv: Data) -> Int32? {
    let array = iv.toArray(type: Int32.self)
    guard array.count == 4 else { return nil }

    let r0 = array[0].bigEndian
    let r1 = array[1].bigEndian
    let r2 = array[2].bigEndian

    return r2 ^ r1 ^ r0
}

static func extractGuidFromIV(iv: Data) -> Int32? {
    let array = iv.toArray(type: Int32.self)
    guard array.count == 4 else { return nil }

    let r0 = array[0].bigEndian
    let r1 = array[1].bigEndian
    let r2 = array[2].bigEndian
    let r3 = array[3].bigEndian

    return r3 ^ r2 ^ r1 ^ r0
}

【问题讨论】:

  • 谢谢@Rob 我添加了更多关于如何使用它们的信息。
  • 你的代码看起来像来自round trip Swift number types to/from Data 的 Swift 4 和 Swift 5 版本——你可以留下评论并要求澄清:)

标签: swift generics unsafe-pointers unsafemutablepointer


【解决方案1】:

我会直接使用建议的替换,即withUnsafeBytes(_:),其第一个参数是UnsafeRawBufferPointer,而不是构建数组或不必要地复制缓冲区,例如:

static func extractPacketSizeFromIV(iv: Data) -> Int32? {
    return iv.withUnsafeBytes { rawBuffer -> Int32 in
        let buffer = rawBuffer.bindMemory(to: Int32.self)
        let r0 = buffer[0].bigEndian
        let r1 = buffer[1].bigEndian
        let r2 = buffer[2].bigEndian

        return r2 ^ r1 ^ r0
    }
}

显然,如果您的 Data 比这更复杂(例如,具有许多不同类型的不同大小的异构有效负载),则可能需要不同的方法,但如果这是一个简单的缓冲区,只有一个简单的集合Int32,上面是检索必要值的有效方法。

【讨论】:

  • ...如果底层内存针对 Int32 值对齐。
【解决方案2】:

首先,您的toArray 是在Data 的扩展中定义的,对吧?

(请在写问题时澄清这些事情。)

您的代码将与您的用例中的以前开发人员的代码以相同的方式工作,但我会在 Swift 5 中编写类似的代码:

func toArray<T>(type: T.Type) -> [T] {
    return self.withUnsafeBytes {
        [T]($0.bindMemory(to: type))
    }
}

【讨论】:

  • bindMemory 的潜在问题是它要求内存为绑定类型正确对齐,通常很难判断给定数据值的内存如何对齐。这就是为什么我在 stackoverflow.com/a/38024025/1187415 中建议使用 copyMemory。
  • 是的,当然,但是这个问题清楚地表明Data 仅由这三个/四个Int32 值组成,所以我不会用copyMemory 不必要地使这个复杂化或者你有什么(特别是如果缓冲区很大,同质集合)。当然,如果您有一个更复杂的Data,其中包含不同大小的异构数据类型,您会更上一层楼,但恕我直言。
猜你喜欢
  • 2019-06-05
  • 2023-03-15
  • 2023-04-04
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 2020-10-04
  • 2012-03-17
  • 1970-01-01
相关资源
最近更新 更多