Являются ли эти функции памяти одинаковыми для Swift 5 Conversion UnsafeBufferPointer - PullRequest
1 голос
/ 10 мая 2019

Я делаю некоторые преобразования 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
}

Используется в контексте этих двух валют:

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
}

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Я бы использовал предложенную замену, а именно 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, выше приведен эффективный способ получения необходимых значений.

1 голос
/ 10 мая 2019

Прежде всего, ваш toArray определяется как расширение Data, верно?

(Пожалуйста, уточните такие вещи при написании вопросов.)

Ваш код будет работать так же, как код от предыдущего разработчика в вашем случае использования, но я бы написал эквивалент в Swift 5 следующим образом:

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

bindMemory(to: type) создает UnsafeBufferPointer<T> (как в исходном коде) из параметра, переданного из нового withUnsafeBytes - UnsafeRawBufferPointer.

...