I need to create create a data stream that contains multiple parameters, send it over the network and then extract those parameter when I receive the data. This is how and create my data (I'm certain all of my variables contain a value)
let dataToSend = NSMutableData()
var mType = Int32(messageType.rawValue)
var reqId = Int32(requestId)
dataToSend.appendDataWithUnsafeBytes(from: &mType, of: Int32.self)
dataToSend.appendDataWithUnsafeBytes(from: &reqId, of: Int32.self)
/* extra protocol data length. In version 0, this is0 as thereis no extra data.
In the future, if you need to add extra protocol data use this*/
var unUsedProtocol = Int32(0)
dataToSend.appendDataWithUnsafeBytes(from: &unUsedProtocol, of: Int32.self)
var encodedDataJson = !jsonString.isEmptyOrNil ? jsonString?.asciiValues : [UInt8]()
dataToSend.appendDataWithUnsafeBytes(from: &encodedDataJson, of: [UInt8]?.self)
var bData = bindaryData
dataToSend.appendDataWithUnsafeBytes(from: &bData, of: Data.self)
here is my appendDataWithUnsafeBytes NSMutableData extension.
extension NSMutableData {
func appendDataWithUnsafeBytes<T>(from element: inout T, of type: T.Type) {
let size = MemoryLayout.size(ofValue: element)
withUnsafeBytes(of: &element) { ptr in
let buffer = ptr.bindMemory(to: type)
if let address = buffer.baseAddress {
self.append(address, length: size)
} else {
VsLogger.logDebug("appendDataWithUnsafeBytes", "unable to get base address of pointer of type: \(type)")
}
}
}
}
and this is how try to extract it (I get the index value along with the data)
var messageTypeValue: Int32? = nil
var requestId: Int32? = nil
var encodedJsonData: Data? = nil
var binaryData: Data? = nil
let intSize = MemoryLayout<Int32>.size
let dataSize = MemoryLayout<Data>.size
var offset = index
bufferData.getBytes(&messageTypeValue, range: NSRange(location: offset, length: intSize))
offset += intSize //8
bufferData.getBytes(&requestId, range: NSRange(location: offset, length: intSize))
offset += intSize //12
/*skipping extra bytes (unsuedProtocol in sendMessageFunction). They come from a future version
that this code doesn't understand*/
offset += intSize //16
bufferData.getBytes(&encodedJsonData, range: NSRange(location: offset, length: dataSize))
offset += dataSize //32
bufferData.getBytes(&binaryData, range: NSRange(location: offset, length: dataSize))
I'm only able to get the first value (messageTypeValue) but for the rest I either get nil or not the right data.
Thank you!
***** UPDATE *****
I got it working by modifying my sending and receiving functions as follows. Where I send it.
let dataToSend = NSMutableData()
var mType = Int32(messageType.rawValue)
var reqId = Int32(requestId)
dataToSend.appendDataWithUnsafeBytes(from: &mType, of: Int32.self)
dataToSend.appendDataWithUnsafeBytes(from: &reqId, of: Int32.self)
/* estra protocol data length. In version 0, this is0 as thereis no extra data.
In the future, if you need to add extra protocol data use this*/
var unUsedProtocol = Int32(0)
dataToSend.appendDataWithUnsafeBytes(from: &unUsedProtocol, of: Int32.self)
var jsonData = Data(!jsonString.isEmptyOrNil ? jsonString!.asciiValues : [UInt8]())
dataToSend.appendDataWithUnsafeBytes(from: &jsonData, of: Data.self)
var bData = bindaryData
dataToSend.appendDataWithUnsafeBytes(from: &bData, of: Data.self)
where I receive it
var offset = Int(index)
let int32Size = MemoryLayout<Int32>.size
let dataSize = MemoryLayout<Data>.size
let messageTypeValue = (bufferData.bytes + offset).load(as: Int32.self)
offset += int32Size
let requestId = (bufferData.bytes + offset).load(as: Int32.self)
offset += int32Size
//skip this one since it not used
//let unusedProtocol = (bufferData.bytes + offset).load(as: Int32.self)
offset += int32Size
let encodedJsonData = (bufferData.bytes + offset).load(as: Data.self)
offset += dataSize
let binaryData = bufferData.bytes.load(fromByteOffset: offset, as: Data.self)
the data is supposed to always be align properly, but is there a way to do some error checking on bufferData.bytes.load(fromByteOffset:as:)