UnsafePointer
can be implicitly cast to UnsafeRawPointers
when passed as parameters:
var x = 42
func print<T>(address p: UnsafeRawPointer, as type: T.Type) {
print(p.load(as: type))
}
withUnsafePointer(to: &x) { (ptr) in
print(address: ptr, as: Int.self) // Prints "42"
}
However, it seems that UnsafeBufferPointer
cannot be implicitly cast to UnsafeRawBufferPointer
:
var x = 42
func printBuffer<T>(address p: UnsafeRawBufferPointer, as type: T.Type) {
print(p.load(as: type))
}
withUnsafePointer(to: &x) { (ptr) in
let buff = UnsafeBufferPointer(start: ptr, count: 1)
printBuffer(address: buff, as: Int.self) // 1
}
In this snippet, the line marked // 1
errors:
cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeRawBufferPointer'
Why is this implicit conversion not possible, when the previous one is allowed?
You cannot cast a UnsafeBufferPointer
to a UnsafeRawBufferPointer
because that is more than reinterpreting the pointer: It requires
to calculate the raw byte count.
But you can create a UnsafeRawBufferPointer
from a UnsafeBufferPointer
:
withUnsafePointer(to: &x) { (ptr) in
let buff = UnsafeBufferPointer(start: ptr, count: 1)
let rawBuff = UnsafeRawBufferPointer.init(buff)
printBuffer(address: rawBuff, as: Int.self)
}
Here is the implementation of that initializer in UnsafeRawBufferPointer.swift.gyb:
/// Creates a raw buffer over the contiguous bytes in the given typed buffer.
///
/// - Parameter buffer: The typed buffer to convert to a raw buffer. The
/// buffer's type `T` must be a trivial type.
@_inlineable
public init<T>(_ buffer: UnsafeMutableBufferPointer<T>) {
self.init(start: buffer.baseAddress!,
count: buffer.count * MemoryLayout<T>.stride)
}