I am trying to use a CircularBuffer<UInt8>
from SwiftNIO to store data and once the buffer is almost full dump the contents to a file using an OutputStream
. Unfortunately, the OutputStream.write()
method takes UnsafePointer
as an argument, while the CircularBuffer
can output UnsafeBufferPointer
. Is there a way to convert CircularBuffer
to UnsafePointer
?
I have tried to extend CircularBuffer with the following code that I am using with success to convert structs to Byte arrays as it was suggested that CircularBuffer is in fact a struct, but I am getting garbage in my output file:
extension CircularBuffer {
func toBytes() -> [UInt8] {
let capacity = MemoryLayout<Self>.size
var mutableValue = self
return withUnsafePointer(to: &mutableValue) {
return $0.withMemoryRebound(to: UInt8.self, capacity: capacity) {
return Array(UnsafeBufferPointer(start: $0, count: capacity))
}
}
}
}
Any thoughts?
CircularBuffer
is a struct with an internal ContiguousArray
for the element storage. ContiguousArray
is also a struct, with internal pointers to the actual element storage.
Your current code produce garbage because it returns the memory representation of the struct CircularBuffer
itself, and not the bytes of the elements which it represents.
As a collection, CircularBuffer
has a withContiguousStorageIfAvailable()
method which calls a closure with a pointer to the element storage if such contiguous storage exists. The closure is called with an UnsafeBufferPointer
argument from which you can obtain the baseAddress
:
var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let amountWritten = buffer.withContiguousStorageIfAvailable {
os.write($0.baseAddress!, maxLength: $0.count)
}
But there is a problem: CircularBuffer
just inherits the default implementation from Sequence
which returns nil
without calling the closure. This is a known issue. So the above code would compile, but not work.
A simple way (at the cost of copying the contents) would be to use that you can initialize an array from a collection:
var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let contents = Array(buffer)
let amountWritten = os.write(contents, maxLength: contents.count)