//===--- FixedArray.swift.gyb ---------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// %{ # The sizes to generate code for. sizes = [2, 8, 16] }% % for N in sizes: @usableFromInline // FIXME(sil-serialize-all) @_fixed_layout // FIXME(sil-serialize-all) internal struct _FixedArray${N} { // ABI TODO: The has assumptions about tuple layout in the ABI, namely that // they are laid out contiguously and individually addressable (i.e. strided). // @usableFromInline // FIXME(sil-serialize-all) internal var storage: ( // A ${N}-wide tuple of type T % for i in range(0, N-1): T, % end T ) @usableFromInline // FIXME(sil-serialize-all) var _count: Int8 } extension _FixedArray${N} { @inlinable // FIXME(sil-serialize-all) internal static var capacity: Int { @inline(__always) get { return ${N} } } @inlinable // FIXME(sil-serialize-all) internal var capacity: Int { @inline(__always) get { return ${N} } } @inlinable // FIXME(sil-serialize-all) internal var count: Int { @inline(__always) get { return Int(truncatingIfNeeded: _count) } @inline(__always) set { _count = Int8(newValue) } } } extension _FixedArray${N} : RandomAccessCollection, MutableCollection { internal typealias Index = Int @inlinable // FIXME(sil-serialize-all) internal var startIndex : Index { return 0 } @inlinable // FIXME(sil-serialize-all) internal var endIndex : Index { return count } @inlinable // FIXME(sil-serialize-all) internal subscript(i: Index) -> T { @inline(__always) get { let count = self.count // for exclusive access _sanityCheck(i >= 0 && i < count) var copy = storage let res: T = withUnsafeBytes(of: ©) { (rawPtr : UnsafeRawBufferPointer) -> T in let stride = MemoryLayout.stride _sanityCheck(rawPtr.count == ${N}*stride, "layout mismatch?") let bufPtr = UnsafeBufferPointer( start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self), count: count) return bufPtr[i] } return res } @inline(__always) set { _sanityCheck(i >= 0 && i < count) self.withUnsafeMutableBufferPointer { buffer in buffer[i] = newValue } } } @inlinable // FIXME(sil-serialize-all) @inline(__always) internal func index(after i: Index) -> Index { return i+1 } @inlinable // FIXME(sil-serialize-all) @inline(__always) internal func index(before i: Index) -> Index { return i-1 } } extension _FixedArray${N} { @inlinable // FIXME(sil-serialize-all) internal mutating func append(_ newElement: T) { _sanityCheck(count < capacity) _count += 1 self[count-1] = newElement } } extension _FixedArray${N} where T : ExpressibleByIntegerLiteral { @inlinable // FIXME(sil-serialize-all) @inline(__always) internal init(count: Int) { _sanityCheck(count >= 0 && count <= _FixedArray${N}.capacity) self.storage = ( % for i in range(0, N-1): 0, % end 0 ) self._count = Int8(truncatingIfNeeded: count) } @inlinable // FIXME(sil-serialize-all) @inline(__always) internal init() { self.init(count: 0) } @inlinable // FIXME(sil-serialize-all) @inline(__always) internal init(allZeros: ()) { self.init(count: ${N}) } } extension _FixedArray${N} { @inlinable // FIXME(sil-serialize-all) internal mutating func withUnsafeMutableBufferPointer( _ body: (UnsafeMutableBufferPointer) throws -> R ) rethrows -> R { let count = self.count // for exclusive access return try withUnsafeMutableBytes(of: &storage) { rawBuffer in _sanityCheck(rawBuffer.count == ${N}*MemoryLayout.stride, "layout mismatch?") let buffer = UnsafeMutableBufferPointer( start: rawBuffer.baseAddress._unsafelyUnwrappedUnchecked .assumingMemoryBound(to: Element.self), count: count) return try body(buffer) } } @inlinable // FIXME(sil-serialize-all) internal mutating func withUnsafeBufferPointer( _ body: (UnsafeBufferPointer) throws -> R ) rethrows -> R { let count = self.count // for exclusive access return try withUnsafeBytes(of: &storage) { rawBuffer in _sanityCheck(rawBuffer.count == ${N}*MemoryLayout.stride, "layout mismatch?") let buffer = UnsafeBufferPointer( start: rawBuffer.baseAddress._unsafelyUnwrappedUnchecked .assumingMemoryBound(to: Element.self), count: count) return try body(buffer) } } } % end