Skip to content

Commit a05a66c

Browse files
committed
[stdlib] Dictionary.Keys, .Values: Implement custom iterators
1 parent 8c8f822 commit a05a66c

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
@@ -1488,6 +1488,66 @@ extension Dictionary {
14881488
}
14891489
}
14901490

1491+
extension Dictionary.Keys {
1492+
@_fixed_layout
1493+
public struct Iterator: IteratorProtocol {
1494+
@usableFromInline
1495+
internal var _base: Dictionary<Key, Value>.Iterator
1496+
1497+
@inlinable
1498+
internal init(_ base: Dictionary<Key, Value>.Iterator) {
1499+
self._base = base
1500+
}
1501+
1502+
@inlinable
1503+
public mutating func next() -> Key? {
1504+
#if _runtime(_ObjC)
1505+
if case .cocoa(let cocoa) = _base._variant {
1506+
_base._cocoaPath()
1507+
guard let cocoaKey = cocoa.nextKey() else { return nil }
1508+
return _forceBridgeFromObjectiveC(cocoaKey, Key.self)
1509+
}
1510+
#endif
1511+
return _base._asNative.nextKey()
1512+
}
1513+
}
1514+
1515+
@inlinable
1516+
public func makeIterator() -> Iterator {
1517+
return Iterator(_variant.makeIterator())
1518+
}
1519+
}
1520+
1521+
extension Dictionary.Values {
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() -> Value? {
1534+
#if _runtime(_ObjC)
1535+
if case .cocoa(let cocoa) = _base._variant {
1536+
_base._cocoaPath()
1537+
guard let (_, cocoaValue) = cocoa.next() else { return nil }
1538+
return _forceBridgeFromObjectiveC(cocoaValue, Value.self)
1539+
}
1540+
#endif
1541+
return _base._asNative.nextValue()
1542+
}
1543+
}
1544+
1545+
@inlinable
1546+
public func makeIterator() -> Iterator {
1547+
return Iterator(_variant.makeIterator())
1548+
}
1549+
}
1550+
14911551
extension Dictionary: Equatable where Value: Equatable {
14921552
@inlinable
14931553
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
@@ -685,7 +685,7 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
685685
internal typealias Element = (key: AnyObject, value: AnyObject)
686686

687687
@usableFromInline
688-
internal func next() -> Element? {
688+
internal func nextKey() -> AnyObject? {
689689
if itemIndex < 0 {
690690
return nil
691691
}
@@ -713,6 +713,12 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
713713
let itemsPtr = _UnmanagedAnyObjectArray(itemsPtrUP)
714714
let key: AnyObject = itemsPtr[itemIndex]
715715
itemIndex += 1
716+
return key
717+
}
718+
719+
@usableFromInline
720+
internal func next() -> Element? {
721+
guard let key = nextKey() else { return nil }
716722
let value: AnyObject = base.object.object(forKey: key)!
717723
return (key, value)
718724
}

stdlib/public/core/NativeDictionary.swift

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

591+
@inlinable
592+
internal mutating func nextKey() -> Key? {
593+
guard let index = iterator.next() else { return nil }
594+
return base.uncheckedKey(at: index)
595+
}
596+
597+
@inlinable
598+
internal mutating func nextValue() -> Value? {
599+
guard let index = iterator.next() else { return nil }
600+
return base.uncheckedValue(at: index)
601+
}
602+
591603
@inlinable
592604
internal mutating func next() -> Element? {
593605
guard let index = iterator.next() else { return nil }

0 commit comments

Comments
 (0)