mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[stdlib] Make protocol _NSArrayCore internal
These shadow protocols don’t add any real type safety, and exposing them in the ABI seems unnecessary.
This commit is contained in:
@@ -21,29 +21,76 @@
|
||||
#if _runtime(_ObjC)
|
||||
import SwiftShims
|
||||
|
||||
/// A wrapper around any `_NSArrayCore` that gives it
|
||||
/// `Collection` conformance. Why not make
|
||||
/// `_NSArrayCore` conform directly? It's a class, and I
|
||||
/// don't want to pay for the dynamic dispatch overhead.
|
||||
/// A wrapper around any `_NSArrayCore` (represented as AnyObject) that gives it
|
||||
/// `Collection` conformance. Why not make `_NSArrayCore` conform directly?
|
||||
/// It's a class, and I don't want to pay for the dynamic dispatch overhead.
|
||||
@usableFromInline
|
||||
@_fixed_layout
|
||||
internal struct _CocoaArrayWrapper : RandomAccessCollection {
|
||||
@usableFromInline
|
||||
typealias Indices = Range<Int>
|
||||
|
||||
@usableFromInline
|
||||
internal var buffer: AnyObject
|
||||
|
||||
@usableFromInline @_transparent
|
||||
internal init(_ buffer: AnyObject) {
|
||||
self.buffer = buffer
|
||||
}
|
||||
|
||||
internal var core: _NSArrayCore {
|
||||
@inline(__always) get {
|
||||
return unsafeBitCast(buffer, to: _NSArrayCore.self)
|
||||
}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
internal var startIndex: Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
internal var endIndex: Int {
|
||||
return buffer.count
|
||||
return core.count
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@usableFromInline
|
||||
internal subscript(i: Int) -> AnyObject {
|
||||
return buffer.objectAt(i)
|
||||
return core.objectAt(i)
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
internal subscript(bounds: Range<Int>) -> _SliceBuffer<AnyObject> {
|
||||
let boundsCount = bounds.count
|
||||
if boundsCount == 0 {
|
||||
return _SliceBuffer(
|
||||
_buffer: _ContiguousArrayBuffer<AnyObject>(),
|
||||
shiftedToStartIndex: bounds.lowerBound)
|
||||
}
|
||||
|
||||
// Look for contiguous storage in the NSArray
|
||||
let cocoaStorageBaseAddress = self.contiguousStorage(self.indices)
|
||||
|
||||
if let cocoaStorageBaseAddress = cocoaStorageBaseAddress {
|
||||
return _SliceBuffer(
|
||||
owner: self.buffer,
|
||||
subscriptBaseAddress: cocoaStorageBaseAddress,
|
||||
indices: bounds,
|
||||
hasNativeBuffer: false)
|
||||
}
|
||||
|
||||
// No contiguous storage found; we must allocate
|
||||
let result = _ContiguousArrayBuffer<AnyObject>(
|
||||
_uninitializedCount: boundsCount,
|
||||
minimumCapacity: 0)
|
||||
|
||||
// Tell Cocoa to copy the objects into our storage
|
||||
core.getObjects(
|
||||
UnsafeMutableRawPointer(result.firstElementAddress)
|
||||
.assumingMemoryBound(to: AnyObject.self),
|
||||
range: _SwiftNSRange(location: bounds.lowerBound, length: boundsCount))
|
||||
|
||||
return _SliceBuffer(_buffer: result, shiftedToStartIndex: bounds.lowerBound)
|
||||
}
|
||||
|
||||
/// Returns a pointer to the first element in the given non-empty `subRange`
|
||||
@@ -56,7 +103,6 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
|
||||
/// is sometimes conservative and may return `nil` even when
|
||||
/// contiguous storage exists, e.g., if array doesn't have a smart
|
||||
/// implementation of countByEnumerating.
|
||||
@inlinable
|
||||
internal func contiguousStorage(
|
||||
_ subRange: Range<Int>
|
||||
) -> UnsafeMutablePointer<AnyObject>?
|
||||
@@ -69,9 +115,9 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
|
||||
// acceptable conservative behavior, but could potentially be
|
||||
// optimized for other cases.
|
||||
let contiguousCount = withUnsafeMutablePointer(to: &enumerationState) {
|
||||
self.buffer.countByEnumerating(with: $0, objects: nil, count: 0)
|
||||
core.countByEnumerating(with: $0, objects: nil, count: 0)
|
||||
}
|
||||
|
||||
|
||||
return contiguousCount >= subRange.upperBound
|
||||
? UnsafeMutableRawPointer(enumerationState.itemsPtr!)
|
||||
.assumingMemoryBound(to: AnyObject.self)
|
||||
@@ -79,12 +125,25 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
|
||||
: nil
|
||||
}
|
||||
|
||||
@usableFromInline @_transparent
|
||||
internal init(_ buffer: _NSArrayCore) {
|
||||
self.buffer = buffer
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
internal var buffer: _NSArrayCore
|
||||
__consuming internal func _copyContents(
|
||||
subRange bounds: Range<Int>,
|
||||
initializing target: UnsafeMutablePointer<AnyObject>
|
||||
) -> UnsafeMutablePointer<AnyObject> {
|
||||
let nsSubRange = SwiftShims._SwiftNSRange(
|
||||
location: bounds.lowerBound,
|
||||
length: bounds.upperBound - bounds.lowerBound)
|
||||
|
||||
// Copies the references out of the NSArray without retaining them
|
||||
core.getObjects(target, range: nsSubRange)
|
||||
|
||||
// Make another pass to retain the copied objects
|
||||
var result = target
|
||||
for _ in bounds {
|
||||
result.initialize(to: result.pointee)
|
||||
result += 1
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user