Convert an Array (of known fixed size) to a tuple

To round this out, I wrote this as a global function, so that structs with tuple pseudo-arrays can be accessed without having to extend each one explicitly. My version:

func withUnsafeMutableBufferPointer<Struct,Element,Tuple,R>(
    to value: inout Struct,
    at property: WritableKeyPath<Struct,Tuple>,
    using type: Element.Type,
    _ body: (UnsafeMutableBufferPointer<Element>) throws -> R) rethrows -> R {
    return try withUnsafeMutablePointer(to: &value [keyPath: property]) {
        let count = MemoryLayout<Tuple>.stride / MemoryLayout<Element>.stride
        return try $0.withMemoryRebound(to: Element.self, capacity: count) {
            return try body(UnsafeMutableBufferPointer(start: $0, count: count))
        }
    }
}

used like this:

    struct Uniforms { // assume this came from an imported header
        var weights: (Float, Float, Float, Float)
    }

    var uniforms = Uniforms(weights: (1,2,3,4))
    print("Uniforms: \(uniforms)") // 'Uniforms: Uniforms(weights: (1.0, 2.0, 3.0, 4.0))'
    withUnsafeMutableBufferPointer(to: &uniforms, at: \.weights, using: Float.self) {
        for index in 0 ..< $0.count {
            $0 [index] *= 2
        }
    }
    print("Uniforms: \(uniforms)") // 'Uniforms: Uniforms(weights: (2.0, 4.0, 6.0, 8.0))'

Ideally, though, I'd like to see the C header importer conform such structs to a protocol that provides this functionality as an instance method. I'd also like to see a distinction between accessing a fixed size C array (Unsafe[Mutable]BufferPointer) and a variable size C array (Unsafe[Mutable]Pointer).

2 Likes