Skip to content

Commit e080bab

Browse files
authored
Merge pull request #19602 from lorentey/dict-iterators
[stdlib] Dictionary.Keys, .Values: Implement custom iterators
2 parents e5d711c + a05a66c commit e080bab

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

stdlib/public/core/Dictionary.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,66 @@ extension Dictionary {
15181518
}
15191519
}
15201520

1521+
extension Dictionary.Keys {
1522+
@_fixed_layout
1523+
public struct Iterator: IteratorProtocol {
1524+
@usableFromInline
1525+
internal var _base: Dictionary<Key, Value>.Iterator
1526+
1527+
@inlinable
1528+
internal init(_ base: Dictionary<Key, Value>.Iterator) {
1529+
self._base = base
1530+
}
1531+
1532+
@inlinable
1533+
public mutating func next() -> Key? {
1534+
#if _runtime(_ObjC)
1535+
if case .cocoa(let cocoa) = _base._variant {
1536+
_base._cocoaPath()
1537+
guard let cocoaKey = cocoa.nextKey() else { return nil }
1538+
return _forceBridgeFromObjectiveC(cocoaKey, Key.self)
1539+
}
1540+
#endif
1541+
return _base._asNative.nextKey()
1542+
}
1543+
}
1544+
1545+
@inlinable
1546+
public func makeIterator() -> Iterator {
1547+
return Iterator(_variant.makeIterator())
1548+
}
1549+
}
1550+
1551+
extension Dictionary.Values {
1552+
@_fixed_layout
1553+
public struct Iterator: IteratorProtocol {
1554+
@usableFromInline
1555+
internal var _base: Dictionary<Key, Value>.Iterator
1556+
1557+
@inlinable
1558+
internal init(_ base: Dictionary<Key, Value>.Iterator) {
1559+
self._base = base
1560+
}
1561+
1562+
@inlinable
1563+
public mutating func next() -> Value? {
1564+
#if _runtime(_ObjC)
1565+
if case .cocoa(let cocoa) = _base._variant {
1566+
_base._cocoaPath()
1567+
guard let (_, cocoaValue) = cocoa.next() else { return nil }
1568+
return _forceBridgeFromObjectiveC(cocoaValue, Value.self)
1569+
}
1570+
#endif
1571+
return _base._asNative.nextValue()
1572+
}
1573+
}
1574+
1575+
@inlinable
1576+
public func makeIterator() -> Iterator {
1577+
return Iterator(_variant.makeIterator())
1578+
}
1579+
}
1580+
15211581
extension Dictionary: Equatable where Value: Equatable {
15221582
@inlinable
15231583
public static func == (lhs: [Key: Value], rhs: [Key: Value]) -> Bool {

stdlib/public/core/DictionaryBridging.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
705705
internal typealias Element = (key: AnyObject, value: AnyObject)
706706

707707
@usableFromInline
708-
internal func next() -> Element? {
708+
internal func nextKey() -> AnyObject? {
709709
if itemIndex < 0 {
710710
return nil
711711
}
@@ -733,6 +733,12 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
733733
let itemsPtr = _UnmanagedAnyObjectArray(itemsPtrUP)
734734
let key: AnyObject = itemsPtr[itemIndex]
735735
itemIndex += 1
736+
return key
737+
}
738+
739+
@usableFromInline
740+
internal func next() -> Element? {
741+
guard let key = nextKey() else { return nil }
736742
let value: AnyObject = base.object.object(forKey: key)!
737743
return (key, value)
738744
}

stdlib/public/core/NativeDictionary.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,18 @@ extension _NativeDictionary.Iterator: IteratorProtocol {
653653
@usableFromInline
654654
internal typealias Element = (key: Key, value: Value)
655655

656+
@inlinable
657+
internal mutating func nextKey() -> Key? {
658+
guard let index = iterator.next() else { return nil }
659+
return base.uncheckedKey(at: index)
660+
}
661+
662+
@inlinable
663+
internal mutating func nextValue() -> Value? {
664+
guard let index = iterator.next() else { return nil }
665+
return base.uncheckedValue(at: index)
666+
}
667+
656668
@inlinable
657669
internal mutating func next() -> Element? {
658670
guard let index = iterator.next() else { return nil }

0 commit comments

Comments
 (0)