Как преобразовать значения разных типов в байт данных - PullRequest
0 голосов
/ 26 августа 2018

Я пишу приложение, в котором мне нужно преобразовать массив данных различных типов в массив данных, который я отправлю на другое устройство через порт UDP.

Пока у меня есть следующий код:

class ViewController: NSViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    let a: UInt8 = 42

    var da:[UInt8] = [a]
    let data = Data(buffer: UnsafeBufferPointer(start: &da, count: da.count))
    let x = data.toArray(type: UInt8.self)
    print(x)
  }
}

Пока это работает.Я получаю следующий вывод: [42]
Если бы я изменил let a: UInt8 = 42 на let a: Float = 3.14 и var da:[Float] = [a], я получил бы результат [195, 245, 72, 64].

Все вышеперечисленное - это то, чтоЯ жду.Проблема заключается в следующем коде:

class ViewController: NSViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    let b: UInt8 = 42
    let a: Float = 3.14

    var da:[Any] = [a, b]
    let data = Data(buffer: UnsafeBufferPointer(start: &da, count: da.count))
    let x = data.toArray(type: UInt8.self)
    print(x)
  }
}

Здесь я ожидаю получить [42, 195, 245, 72, 64], за исключением того, что получаю следующий результат: [42, 0, 0, 0, 0, 0, 0, 0, 176, 10, 10, 0, 0, 96, 0, 0, 104, 41, 172, 143, 255, 127, 0, 0, 32, 161, 114, 0, 1, 0, 0, 0, 195, 245, 72, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 228, 32, 1, 1, 0, 0, 0, 168, 153, 114, 0, 1, 0, 0, 0].

Может кто-нибудь объяснить мнепочему это происходит и что я должен изменить, чтобы получить ожидаемый результат?

Edit: Хотя я мог пропустить заполнение, я пытаюсь подделать сервер, который соответствует приведенной ниже спецификации, в то время какЯ занимаюсь разработкой приложения.
https://forums.codemasters.com/discussion/136948/f1-2018-udp-specification#latest

1 Ответ

0 голосов
/ 26 августа 2018

Вы видите представление внутренней памяти Any.

print(MemoryLayout<Any>.size) //-> 32

Значение типа Any представлено в скрытой структуре размера 32, которая может содержать необработанное значение некоторых примитивных данных или адрес экземпляра ссылочного типа или огромную структуру, а также некоторые метаданные о типе содержащегося значения.

Это не просто заполнение.


Вы можете написать что-то вроде этого:

(Возможно, вам придется самостоятельно контролировать заполнение , если это необходимо.)

protocol ByteRepresentable {
    var bytes: Data {get}
}
extension ByteRepresentable {
    var bytes: Data {
        var copiedSelf = self
        return Data(bytes: &copiedSelf, count: MemoryLayout.size(ofValue: self))
    }
}
extension UInt8: ByteRepresentable {}
extension Float: ByteRepresentable {}
//...

let a: UInt8 = 42
let b: Float = 3.14

let da: [ByteRepresentable] = [a, b]
var data = da.reduce(into: Data(), {$0.append($1.bytes)})
print(Array(data)) //->[42, 195, 245, 72, 64]

Если вы хотите написать расширение:

extension Array where Element == ByteRepresentable {
    func toData() -> Data {
        return self.reduce(into: Data(), {$0.append($1.bytes)})
    }
}

print(Array(da.toData())) //->[42, 195, 245, 72, 64]
...