Swift doesn't have fixed size arrays, and I guess many of us have experimented with various workarounds.
I thought it would be fun to share and discuss our ways around Swift's lack of fixed size arrays here.
From the very simple ones like:
var myFixedSizeArrayOfEightInts = (0, 0, 0, 0, 0, 0, 0, 0)
and
var myFourFloats = SIMD4<Float>
to more involved "solutions" like eg:
protocol FixedSizeArray : ExpressibleByArrayLiteral, RandomAccessCollection where Index == Int {
associatedtype Element
associatedtype Storage
var storage: Storage { get set }
init(elementForIndex: (Int) -> Element)
}
extension FixedSizeArray {
static var count: Int {
let storageSize = MemoryLayout<Storage>.size
let elementStride = MemoryLayout<Element>.stride
precondition(storageSize.isMultiple(of: elementStride))
return storageSize / elementStride
}
var count: Int { return Self.count }
var startIndex: Int { return 0 }
var endIndex: Int { return Self.count }
subscript(position: Int) -> Element {
get {
precondition(0 <= position && position < Self.count, "\(position)")
return self[unchecked: position]
}
set {
precondition(0 <= position && position < Self.count)
self[unchecked: position] = newValue
}
}
subscript(unchecked position: Int) -> Element {
get {
return withUnsafeBytes(of: storage) { (rawPtr) -> Element in
let offset = MemoryLayout<Element>.stride &* position
return rawPtr.load(fromByteOffset: offset, as: Element.self)
}
}
set {
let offset = MemoryLayout<Element>.stride &* position
withUnsafeMutableBytes(of: &storage) { (rawMutPtr) -> Void in
rawMutPtr.storeBytes(of: newValue,
toByteOffset: offset,
as: Element.self)
}
}
}
init(repeating value: Element) {
self.init() { _ in value }
}
init(arrayLiteral elements: Element...) {
precondition(elements.count == Self.count, "Illegal element count")
self.init() { elements[$0] }
}
}
struct FSA2<Element> : FixedSizeArray {
var storage: (Element, Element)
init(elementForIndex efi: (Int) -> Element) {
storage = (efi(0), efi(1))
}
}
// ... Add eg FSA1, FSA3, FSA4, ... as needed ...
struct FSA16<Element> : FixedSizeArray {
var storage: (Element, Element, Element, Element,
Element, Element, Element, Element,
Element, Element, Element, Element,
Element, Element, Element, Element)
init(elementForIndex efi: (Int) -> Element) {
storage = (
efi( 0), efi( 1), efi( 2), efi( 3),
efi( 4), efi( 5), efi( 6), efi( 7),
efi( 8), efi( 9), efi(10), efi(11),
efi(12), efi(13), efi(14), efi(15)
)
}
}