Являются ли эти функции памяти одинаковыми для Swift 5 Conversion UnsafeBufferPointer

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

'withUnsafeBytes' is deprecated: use withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead

для:

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
}

Спасибо @Rob, я добавил больше информации о том, как они используются.

Joshua Hart 10.05.2019 02:54

Ваш код похож на версии Swift 4 и Swift 5 из туда и обратно Типы номеров Swift в/из данных — вы могли бы оставить комментарий и попросить разъяснений :)

Martin R 10.05.2019 06:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
280
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Во-первых, ваш 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.

Потенциальная проблема с bindMemory заключается в том, что он требует, чтобы память была правильно выровнены для связанного типа, и, как правило, трудно сказать, как выровнена память данного значения данных. Вот почему я предложил copyMemory в stackoverflow.com/a/38024025/1187415.

Martin R 10.05.2019 06:49

Да, конечно, но этот вопрос дал понять, что Data состоит только из этих трех/четырех значений Int32, поэтому я бы не стал излишне усложнять это с помощью copyMemory или того, что у вас есть (особенно если буфер был большим, однородная коллекция ). Конечно, если бы у вас был более сложный Data с гетерогенными типами данных разного размера, вы бы подняли его на следующий уровень, но не здесь, ИМХО.

Rob 10.05.2019 08:09

Я бы использовал предложенную замену, а именно 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.

Martin R 10.05.2019 06:49

Другие вопросы по теме