Swift 4 Int32 до [UInt8] - PullRequest
       7

Swift 4 Int32 до [UInt8]

0 голосов
/ 29 сентября 2018

Я пытаюсь получить байты из целого числа в [UInt8], чтобы отправить их по проводному протоколу.Хотя я нашел ответы, которые работают для Swift 2/3, ни одно из решений не работает для Swift 4.

Следующий фрагмент кода работает для кодирования сообщения для сообщений небольшого размера (только необработанные строковые данные с добавлением сетевого байта).размер Int32):

func send(message: String) {
    let messageSize = message.utf8.count
    let encodedMessageSize = Int32(messageSize).bigEndian
    let frameSize = messageSize + 4

    var buffer: [UInt8] = Array()
    buffer.append(0)
    buffer.append(0)
    buffer.append(0)
    buffer.append(UInt8(messageSize))
    buffer.append(contentsOf: message.utf8)
    outputStream.write(buffer, maxLength: frameSize)
}

Я также пытался напрямую использовать необработанные указатели, но не могу заставить работать что-либо для Swift 4 на этом пути.

Общие задачи заключаются в кодировании ифрейм сообщения, которые состоят из целых чисел и строк.Кодировка преобразует все в строки и добавляет ноль в конце каждой строки.Кадрирование просто добавляет к сообщению сетевой порядок байтов размером Int32.Я не могу изменить протокол, но готов рассмотреть другие подходы к достижению этой цели.

ура,

[EDIT] Обновлен код с использованием кода @ MartinR (с предложением @ Hamish).Также достигнут некоторый прогресс в решении общей задачи.

func encodeMessagePart(_ message: String) -> [UInt8] {
    var buffer: [UInt8] = Array(message.utf8)
    buffer.append(0)
    return buffer
}

func encodeMessagePart(_ message: Int) -> [UInt8] {
    return encodeMessagePart("\(message)")
}

func frameMessage(_ buffer: [UInt8]) -> [UInt8] {
    let bufferSize = buffer.count
    var encodedBufferSize = Int32(bufferSize).bigEndian
    let encodedBufferSizeData = withUnsafeBytes(of: &encodedBufferSize) { Data($0) }

    var frame: [UInt8] = Array()
    frame.append(contentsOf: encodedBufferSizeData)
    frame.append(contentsOf: buffer)
    return frame
}

func sendMessage(_ buffer: [UInt8]) {
    let frame = frameMessage(buffer)
    outputStream.write(frame, maxLength: frame.count)
}

func sendMessage(_ message: String) {
    let encodedPart = encodeMessagePart(message)
    sendMessage(encodedPart)
}

//    func sendMessage(_ messages: Encodable...) {
//        var buffer: [UInt8] = Array()
//        for message in messages {
//            let b = encodeMessagePart(message)
//            buffer.append(contentsOf: b)
//        }
//        sendMessage(buffer)
//    }

1 Ответ

0 голосов
/ 29 сентября 2018

Вы можете создать значение Data из целого числа с помощью

let encodedMessageSize = Int32(messageSize).bigEndian
let data = withUnsafeBytes(of: encodedMessageSize) { Data($0) }

(В версиях Swift до 4.2 вам придется писать

var encodedMessageSize = Int32(messageSize).bigEndian
let data = withUnsafeBytes(of: &encodedMessageSize) { Data($0) }

.)

Затем данные могут быть добавлены в массив с помощью

buffer.append(contentsOf: data)

В качестве альтернативы вы можете использовать буфер data вместо массива:

func send(message: String) {
    let messageSize = message.utf8.count
    let encodedMessageSize = Int32(messageSize).bigEndian

    var data = withUnsafeBytes(of: encodedMessageSize) { Data($0) }
    data.append(Data(message.utf8))

    let amountWritten = data.withUnsafeBytes { [count = data.count] in
        outputStream.write($0, maxLength: count)
    }
}

Наконец, обратите внимание, что этоwrite() метод может записать меньше байтов, чем предусмотрено (например, для сетевых подключений), поэтому вы всегда должны проверять возвращаемое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...