I have a protobuf v2 in Swift and I'm trying to append it to another protobuf. This is what I'm trying:
let attachment = getAttachment(id: 987) //From cloud database
var protosData = NSMutableData(data: attachment)
items.forEach { //Some struct array of values
guard let proto = try? MyProtoBuf.Builder()
.setEpochMillis($0.date.epochMilliseconds)
.setValue($0.value)
.build() else { return }
protosData.appendData(proto.data())
}
saveAttachment(protosData) //Store to cloud
It seems I'm like I'm corrupting the data because I get this error when reading it back:
malloc: *** mach_vm_map(size=2749415424) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Perhaps it is my reading back the values is incorrect, here is what I'm doing to read the appended data from storage:
extension GeneratedMessageProtocol {
static func getStreamData(data: NSData) -> [Self] {
var messages = [Self]()
do {
let inStream = NSInputStream(data:data)
inStream.open()
defer { inStream.close() }
while inStream.hasBytesAvailable {
var sizeBuffer: [UInt8] = [0,0,0,0]
inStream.read(&sizeBuffer, maxLength: sizeBuffer.count)
let data = NSData(bytes: sizeBuffer, length: sizeBuffer.count)
let messageSize = data.uint32.littleEndian
var buffer = Array<UInt8>(count: Int(messageSize), repeatedValue: 0)
inStream.read(&buffer, maxLength: Int(messageSize))
let messageData = NSData(bytes: buffer, length:Int(messageSize))
messages.append(try self.parseFromData(messageData))
}
}
catch {
}
return messages
}
}
extension NSData {
var uint32: UInt32 {
get {
var number: UInt32 = 0
self.getBytes(&number, length: sizeof(UInt32))
return number
}
}
}
And here is my protobuf message:
syntax = "proto2";
message MyProtoBuf {
optional uint64 epochMillis = 1;
optional uint32 value = 2;
}
What is the correct way of appending data to an existing protobuf instead of having to parse the array items one by one, appending the protobuf, then converting the whole array back to bytes?
your reading part is ok. you are missing delimiters when chaining proto objects. first calculate and add delimiter to the stream and then the proto object. then do it for each proto object.
let attachment = getAttachment(id: 987) //From cloud database
var arr: [UInt32] = [UInt32(attachment.length)] //Assuming attachment is NSData type
let delimiter = NSData(bytes: arr, length: arr.count * sizeof(UInt32))
let protosData = NSMutableData(data: delimiter)
protosData.appendData(attachment)
items.forEach { //Some struct array of values
guard let proto = try? MyProtoBuf.Builder()
.setEpochMillis($0.date.epochMilliseconds)
.setValue($0.value)
.build() else { return }
var array: [UInt32] = [UInt32(proto.data().length)]
let delimit = NSData(bytes: array, length: arr.count * sizeof(UInt32))
protosData.appendData(delimit)
protosData.appendData(proto.data())
}
saveAttachment(protosData) //Store to cloud
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With