//===--- FixedArray.swift -------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // A helper struct to provide fixed-sized array like functionality // //===----------------------------------------------------------------------===// internal struct _FixedArray16 { // ABI TODO: This makes assumptions about tuple layout in the ABI, namely that // they are laid out contiguously and individually addressable (i.e. strided). // internal var storage: ( // A 16-wide tuple of type T T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T ) var _count: Int8 } extension _FixedArray16 { internal static var capacity: Int { @inline(__always) get { return 16 } } internal var capacity: Int { @inline(__always) get { return 16 } } internal var count: Int { @inline(__always) get { return Int(truncatingIfNeeded: _count) } @inline(__always) set { _count = Int8(newValue) } } } extension _FixedArray16: RandomAccessCollection, MutableCollection { internal typealias Index = Int internal var startIndex: Index { return 0 } internal var endIndex: Index { return count } internal subscript(i: Index) -> T { @inline(__always) get { let count = self.count // for exclusive access _internalInvariant(i >= 0 && i < count) let res: T = withUnsafeBytes(of: storage) { (rawPtr: UnsafeRawBufferPointer) -> T in let stride = MemoryLayout.stride _internalInvariant(rawPtr.count == 16*stride, "layout mismatch?") let bufPtr = UnsafeBufferPointer( start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self), count: count) return bufPtr[_unchecked: i] } return res } @inline(__always) set { _internalInvariant(i >= 0 && i < count) self.withUnsafeMutableBufferPointer { buffer in buffer[_unchecked: i] = newValue } } } @inline(__always) internal func index(after i: Index) -> Index { return i+1 } @inline(__always) internal func index(before i: Index) -> Index { return i-1 } } extension _FixedArray16 { internal mutating func append(_ newElement: T) { _internalInvariant(count < capacity) _count += 1 self[count-1] = newElement } } extension _FixedArray16 where T: ExpressibleByIntegerLiteral { @inline(__always) internal init(count: Int) { _internalInvariant(count >= 0 && count <= _FixedArray16.capacity) self.storage = ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) self._count = Int8(truncatingIfNeeded: count) } @inline(__always) internal init() { self.init(count: 0) } @inline(__always) internal init(allZeros: ()) { self.init(count: 16) } } extension _FixedArray16 { internal mutating func withUnsafeMutableBufferPointer( _ body: (UnsafeMutableBufferPointer) throws -> R ) rethrows -> R { let count = self.count // for exclusive access return try withUnsafeMutableBytes(of: &storage) { rawBuffer in _internalInvariant(rawBuffer.count == 16*MemoryLayout.stride, "layout mismatch?") let buffer = UnsafeMutableBufferPointer( start: rawBuffer.baseAddress._unsafelyUnwrappedUnchecked .assumingMemoryBound(to: Element.self), count: count) return try body(buffer) } } internal mutating func withUnsafeBufferPointer( _ body: (UnsafeBufferPointer) throws -> R ) rethrows -> R { let count = self.count // for exclusive access return try withUnsafeBytes(of: &storage) { rawBuffer in _internalInvariant(rawBuffer.count == 16*MemoryLayout.stride, "layout mismatch?") let buffer = UnsafeBufferPointer( start: rawBuffer.baseAddress._unsafelyUnwrappedUnchecked .assumingMemoryBound(to: Element.self), count: count) return try body(buffer) } } }