ravron
ravron

Reputation: 11211

Implicit conversion from UnsafeBufferPointer to UnsafeRawBufferPointer

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?

Upvotes: 2

Views: 2018

Answers (1)

Martin R
Martin R

Reputation: 539685

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)
  }

Upvotes: 4

Related Questions