Эквивалент Java ByteBuffer в Swift 4 - PullRequest
0 голосов
/ 07 ноября 2018

Я пытаюсь преобразовать свой код Java (Android) в Swift. Я застрял в части ByteBuffer.

private MqttMessage createMqttMessage(boolean encrypted, byte[] message) {
    /* add a zero-byte at the end just to be sure it's terminated although the payload is zero-padded */
    int padding = 16 - ((message.length) % 16);

    /* a zero-byte at the end of the JSON is required for determining the string's end */
    padding = padding == 0 ? 16 : padding;

    byte[] payload = new byte[message.length+padding];

    System.arraycopy(message, 0, payload, 0, message.length);

    /* FRAME_HEADER + JSON-payload + zero-byte + FRAME_TAIL_SIZE */
    int bufferSize = Constants.FRAME_HEADER_SIZE + payload.length + 1 + Constants.FRAME_TAIL_SIZE;

    ByteBuffer frame = ByteBuffer.allocate(bufferSize);

    /* The CC3220 is an ARM device, thus little-endian */
    frame.order(ByteOrder.LITTLE_ENDIAN);

    // message flags (uint8_t)
    byte flags = (byte) (encrypted ? Constants.FRAME_FLAG_ENCRYPTED : 0x0);
    // always use authentication
    flags |= Constants.FRAME_FLAG_AUTHENTICATED;

    frame.put(flags);

    // User token   (uint32_t)
    frame.putInt((int)this.mUserToken);

Что такое эквивалент ByteBuffer в Swift?

Это то, что я имею до сих пор:

private func createMqttMessage(encrypted: Bool, message: [Int8]) {

    var padding:Int = 16 - ((message.count) % 16)

    padding = padding == 0 ? 16 : padding

    var payload:[Int8]

    payload = Array(message[0..<0+message.count])

    let bufferSize = Constants.FRAME_HEADER_SIZE + payload.count + 1 + Constants.FRAME_TAIL_SIZE

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Вы можете использовать это для ByteBuffer .. он ведет себя как Java .. Некоторые функции могут отсутствовать, но их легко добавить.

import Foundation

public class ByteBuffer {

    public init(size: Int) {
        array.reserveCapacity(size)
    }

    public func allocate(_ size: Int) {
        array = [UInt8]()
        array.reserveCapacity(size)
        currentIndex = 0
    }

    public func nativeByteOrder() -> Endianness {
        return hostEndianness
    }

    public func currentByteOrder() -> Endianness {
        return currentEndianness
    }

    public func order(_ endianness: Endianness) -> ByteBuffer {
        currentEndianness = endianness
        return self
    }

    public func put(_ value: UInt8) -> ByteBuffer {
        array.append(value)
        return self
    }

    public func put(_ value: Int32) -> ByteBuffer {
        if currentEndianness == .little {
            array.append(contentsOf: to(value.littleEndian))
            return self
        }

        array.append(contentsOf: to(value.bigEndian))
        return self
    }

    public func put(_ value: Int64) -> ByteBuffer {
        if currentEndianness == .little {
            array.append(contentsOf: to(value.littleEndian))
            return self
        }

        array.append(contentsOf: to(value.bigEndian))
        return self
    }

    public func put(_ value: Int) -> ByteBuffer {
        if currentEndianness == .little {
            array.append(contentsOf: to(value.littleEndian))
            return self
        }

        array.append(contentsOf: to(value.bigEndian))
        return self
    }

    public func put(_ value: Float) -> ByteBuffer {
        if currentEndianness == .little {
            array.append(contentsOf: to(value.bitPattern.littleEndian))
            return self
        }

        array.append(contentsOf: to(value.bitPattern.bigEndian))
        return self
    }

    public func put(_ value: Double) -> ByteBuffer {
        if currentEndianness == .little {
            array.append(contentsOf: to(value.bitPattern.littleEndian))
            return self
        }

        array.append(contentsOf: to(value.bitPattern.bigEndian))
        return self
    }

    public func get() -> UInt8 {
        let result = array[currentIndex]
        currentIndex += 1
        return result
    }

    public func get(_ index: Int) -> UInt8 {
        return array[index]
    }

    public func getInt32() -> Int32 {
        let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<Int32>.size]), Int32.self)
        currentIndex += MemoryLayout<Int32>.size
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getInt32(_ index: Int) -> Int32 {
        let result = from(Array(array[index..<index + MemoryLayout<Int32>.size]), Int32.self)
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getInt64() -> Int64 {
        let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<Int64>.size]), Int64.self)
        currentIndex += MemoryLayout<Int64>.size
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getInt64(_ index: Int) -> Int64 {
        let result = from(Array(array[index..<index + MemoryLayout<Int64>.size]), Int64.self)
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getInt() -> Int {
        let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<Int>.size]), Int.self)
        currentIndex += MemoryLayout<Int>.size
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getInt(_ index: Int) -> Int {
        let result = from(Array(array[index..<index + MemoryLayout<Int>.size]), Int.self)
        return currentEndianness == .little ? result.littleEndian : result.bigEndian
    }

    public func getFloat() -> Float {
        let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<UInt32>.size]), UInt32.self)
        currentIndex += MemoryLayout<UInt32>.size
        return currentEndianness == .little ? Float(bitPattern: result.littleEndian) : Float(bitPattern: result.bigEndian)
    }

    public func getFloat(_ index: Int) -> Float {
        let result = from(Array(array[index..<index + MemoryLayout<UInt32>.size]), UInt32.self)
        return currentEndianness == .little ? Float(bitPattern: result.littleEndian) : Float(bitPattern: result.bigEndian)
    }

    public func getDouble() -> Double {
        let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<UInt64>.size]), UInt64.self)
        currentIndex += MemoryLayout<UInt64>.size
        return currentEndianness == .little ? Double(bitPattern: result.littleEndian) : Double(bitPattern: result.bigEndian)
    }

    public func getDouble(_ index: Int) -> Double {
        let result = from(Array(array[index..<index + MemoryLayout<UInt64>.size]), UInt64.self)
        return currentEndianness == .little ? Double(bitPattern: result.littleEndian) : Double(bitPattern: result.bigEndian)
    }


    public enum Endianness {
        case little
        case big
    }

    private func to<T>(_ value: T) -> [UInt8] {
        var value = value
        return withUnsafeBytes(of: &value, Array.init)
    }

    private func from<T>(_ value: [UInt8], _: T.Type) -> T {
        return value.withUnsafeBytes {
            $0.load(fromByteOffset: 0, as: T.self)
        }
    }

    private var array = [UInt8]()
    private var currentIndex: Int = 0

    private var currentEndianness: Endianness = .big
    private let hostEndianness: Endianness = OSHostByteOrder() == OSLittleEndian ? .little : .big
}

let buffer = ByteBuffer(size: 100)
buffer.order(.big)
buffer.put(1.019001)
buffer.order(.little)
buffer.put(1005)
buffer.order(.big)
buffer.put(1005)

buffer.order(.big)
print(buffer.getDouble())
buffer.order(.little)
print(buffer.getInt())
buffer.order(.big)
print(buffer.getInt())
0 голосов
/ 07 ноября 2018

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

var frame = Data(capacity: bufferSize)

но вам на самом деле не нужно указывать емкость, и вы можете подождать с инициализацией frame, пока у вас фактически не будет каких-либо данных для их инициализации - в зависимости от типа mUserToken вы можете использовать соответствующие Data инициализатор

init(bytes: UnsafeRawPointer, count: Int)
init(bytes: <Array<UInt8>>)
...