JTing
JTing

Reputation: 651

How to convert UInt16 to UInt8 in Swift 3?

I want to convert UInt16 to UInt8 array, but am getting the following error message:

'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.

The code:

    let statusByte: UInt8 = UInt8(status)
    let lenghtByte: UInt16 = UInt16(passwordBytes.count)

    var bigEndian = lenghtByte.bigEndian

    let bytePtr = withUnsafePointer(to: &bigEndian) {
        UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: MemoryLayout.size(ofValue: bigEndian))
    }

Upvotes: 2

Views: 4307

Answers (2)

Leo Dabus
Leo Dabus

Reputation: 236508

You can extend Numeric protocol and create a data property as follow:

Swift 4 or later

extension Numeric {
    var data: Data {
        var source = self
        return Data(bytes: &source, count: MemoryLayout<Self>.size)
    }
}

Since Swift 3 Data conforms to RandomAccessCollection so you can just create an array of bytes from your UInt16 bigEndian data:

extension Data {
    var array: [UInt8] { return Array(self) }
}

let lenghtByte = UInt16(8)
let bytePtr = lenghtByte.bigEndian.data.array   // [0, 8]

Upvotes: 7

Martin R
Martin R

Reputation: 540055

As the error message indicates, you have to use withMemoryRebound() to reinterpret the pointer to UInt16 as a pointer to UInt8:

let bytes = withUnsafePointer(to: &bigEndian) {
    $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: bigEndian)) {
        Array(UnsafeBufferPointer(start: $0, count: MemoryLayout.size(ofValue: bigEndian)))
    }
}

The closures are invoked with pointers ($0) which are only valid for the lifetime of the closure and must not be passed to the outside for later use. That's why an Array is created and used as return value.

There is a simpler solution however:

let bytes = withUnsafeBytes(of: &bigEndian) { Array($0) }

Explanation: withUnsafeBytes invokes the closure with a UnsafeRawBufferPointer to the storage of the bigEndian variable. Since UnsafeRawBufferPointer is a Sequence of UInt8, an array can be created from that with Array($0).

Upvotes: 11

Related Questions