In terms of having two overloads: you unfortunately can't avoid them. ContiguousBytes.withUnsafeBytes
gives you access to the underlying storage of a type which implements ContiguousBytes
, so the buffer given by, say, [UInt8].withUnsafeBytes
will be the actual buffer the array instance is using to store data, not a pointer to itself in memory (e.g. its length, capacity, storage pointer, etc.).
The reason your first overload can't work is that you'd be calling the equivalent of:
withUnsafeBytes { rawBuffer in
rawBuffer.load(as: [Int16].self)
}
where load(as:)
is attempting to read [1, 0, 1, 0]
as if those contents were the length, capacity, and buffer pointer of a single [Int16]
instance, but that's not the case — it's only the contents of bytes
.
You need the second overload in order to create a new array with the contents of that UnsafeRawBufferPointer
.
As for the actual implementation of your array variant, as of SE-0333 Expand usability of withMemoryRebound coming in Swift 5.7, the correct way to do this would be to use withMemoryRebound(to:_:)
, as the unconditional bindMemory(to:)
is unsafe if the buffer was already bound to a different type. withMemoryRebound(to:_:)
is now always safe, even if the buffer is bound, so long as you meet alignment requirements:
/// A raw buffer may represent memory that has been bound to a type.
/// If that is the case, then T
must be layout compatible with the
/// type to which the memory has been bound. This requirement does not
/// apply if the raw buffer represents memory that has not been bound
/// to any type.
This would look like
func load<Element>(_: [Element].Type = [Element].self) -> [Element] {
withUnsafeBytes { rawBuffer in
rawBuffer.withMemoryRebound(to: Element.self) { typedBuffer in
Array(typedBuffer)
}
}
}
UnsafeRawBufferPointer.withMemoryRebound(to:_:)
will do the math on binding the raw bytes to the right stride of Element
, though keep in mind that this is only valid to do if the alignment of the raw buffer matches the alignment requirements of Element
— otherwise you'll either crash or trigger undefined behavior.