I must be really dumb because I sure don't see how to do this. This is what I tried so far, and it's incomplete, but it crashes on the .subdata call with EXC_BREAKPOINT (code=1, subcode=0x1918c38fc). dataWithoutHeader is the deflate-compressed data minus the first two bytes, which cause NSData.decompressed() to fail.
let pageSize = 1024
let arr = try [Float](unsafeUninitializedCapacity: sampleCount)
{ buffer, initializedCount in
print("Count: \(initializedCount)")
var index = 0
let inputFilter = try InputFilter(.decompress, using: .zlib)
{ (length: Int) -> Data? in
let rangeLength = min(length, dataWithoutHeader.count - index)
let subdata = dataWithoutHeader.subdata(in: index ..< index + rangeLength)
index += rangeLength
return subdata
}
var dd = Data()
do
{
while let page = try inputFilter.readData(ofLength: pageSize)
{
dd.append(page)
}
}
catch
{
print("Error: \(error)")
}
// Presumably something here with dd to initialize `buffer, but I have no idea what.
}
The problem I see with this approach (other than I don't know how to actualy do it) is that there’s still an extra copy. There’s the copy that happend during decompression, which obviously can't be avoided. But then in the decompression loop there’s a copy as I append each decompressed page (BTW I don't know how to pick a page size).
In C, I'd just do this:
float* data = (float*) decompressedData;
Surely there’s an equivalent in Swift, I just can't figure out the right incantation of Unsafe[Mutable][Raw][Buffer][Pointer] to do it. Honestly, I hate this aspect of Swift, or at least the documentation around it. Each one is documented in isolation, and there’s no overarching document with nice images and tables to show how each Unsafe* thing relates to the other, and how to do all the typical things the API enables. The lack of example code is a significant weakness of all of Apple's documentation.
Even Array.init(unsafeUninitializedCapacity:initializingWith:) really needs an example to show how to write the closure.
But all in all, this way seems to make it virtually impossible to decompress an array of floats without extra copies.
UPDATE: The crash seems to be due to accessing a subrange of a subrange of the original compressed data, eg:
let dataWithoutHeader = compressedData[2...]
Not sure why that would crash.
UPDATE2: Ah, I see there’s a buffer-based decompression. Let me try that. The front page of the docs, under “Topics,” has “Compressing and decompressing data with input and output filters” and “Compressing and decompressing files with stream compression,” the former of which seemed more appropriate for what I was doing. (Another shortcoming of Apple’s docs: They require reading all of it rather than giving a clear path to the thing you need.)