convert tuple to swift array

Apple Recommended

Replies

[I’m no longer happy with this response. I’ve posted an update to it below.]

I usually do this via UnsafeBufferPointer. For example:

struct Foo {
    var tuple: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
    var array: [UInt8] {
        var tmp = self.tuple
        return [UInt8](UnsafeBufferPointer(start: &tmp.0, count: MemoryLayout.size(ofValue: tmp)))
    }
}

let f = Foo(tuple: (1, 2, 3, 4, 5, 6))
print(f.array)  // prints: [1, 2, 3, 4, 5, 6]

I think that code is clearer. Whether it’s faster is hard to say. You’d have to profile it, which is tricky when you’re dealing with tiny code snippets like this.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • NOTE:

    In the five years since this was posted Swift has changed and it throws a Initialization of 'UnsafeBufferPointer<UInt8>' results in a dangling buffer pointer error on the return [UInt8]... line.

Add a Comment

Thank you Quinn


Just I what I was looking for. I'm not convinced about clearer (too many years of C/C++ and memxxx have always been my friends) but I was concerned about my assumptions involving the number of bytes in the tuple and its alignment.


Bryan

I was concerned about my assumptions involving the number of bytes in the tuple and its alignment.

Yeah, I was concerned about that too. A while back I talked this over with one of the Swift engineers, and they assured me that homogeneous tuple elements would be laid out in a way that’s compatible with

UnsafeBufferPointer
, and thus the
&tmp.0
trick that I used on line 5 is fine.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Check out this source code from Apple: https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/UUID.swift


There are a bunch of different access patterns illustrated in here. One that I hadn't know about was `withUnsafePointer(to:)`.


-Wil

I've adjusted the original answer to make it more generic and also to support the other element types on top of UInt8.

extension Array {
  static func from(tuple: Any, start: UnsafePointer<Element>) -> [Element] {
    [Element](
      UnsafeBufferPointer(
        start: start,
        count: MemoryLayout.size(ofValue: tuple)/MemoryLayout<Element>.size
      )
    )
  }
}

var someTuple: (Double, Double, Double) = (1, 2, 3)
let array: [Double] = .from(tuple: someTuple, start: &someTuple.0)